JavaScript dosyalarına parametre iletme


163

Sıklıkla kullanmak istediğim ve web sayfamda belirli değişkenlerin tanımlanmasını gerektiren bir JavaScript dosyasına sahip olacağım.

Kod böyle bir şey:

<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
   var obj1 = "somevalue";
</script>

Ama yapmak istediğim şey:

<script type="text/javascript" 
     src="file.js?obj1=somevalue&obj2=someothervalue"></script>

Farklı yöntemler denedim ve en iyisi henüz sorgu dizesi böyle ayrıştırmaktır:

var scriptSrc = document.getElementById("myscript").src.toLowerCase();

Ve sonra değerlerimi ara.

Dize ayrıştırmak için bir işlev inşa etmeden bunu yapmak için başka bir yolu olup olmadığını merak ediyorum.

Hepiniz başka yöntemler biliyor musunuz?


9
Bu yinelenen bir soru ( stackoverflow.com/questions/1017424/… ) ve bence yanlış yönlendirilmiş bir tasarım. İlk değişken çözümünüzü (tamam) kullanmak veya betiğin daha sonra değişkenlerle çağrılan bir işlevi tanımlamasını (daha iyi) çok daha basittir.
Matthew Flaschen

Yeni ECMAScript 6 işlevselliğinden yararlanan güncellenmiş bir çözüm arıyorum ... eğer varsa
Chef_Code

Herhangi bir dahili komut dosyası kullanmak, site HTTPS ise ve CSP tam olarak etkinleştirilmişse CSP raporlarını tetikler. CSP belgesinde verilen neden, iç öğelere izin verilmesinin enjeksiyonu kolaylaştırabilmesidir.
David Spector

Yanıtlar:


207

Mümkünse global değişkenleri kullanmamanızı tavsiye ederim. Bağımsız değişkenlerinizi bir nesneye iletmek için bir ad alanı ve OOP kullanın.

Bu kod file.js'ye aittir:

var MYLIBRARY = MYLIBRARY || (function(){
    var _args = {}; // private

    return {
        init : function(Args) {
            _args = Args;
            // some other initialising
        },
        helloWorld : function() {
            alert('Hello World! -' + _args[0]);
        }
    };
}());

Ve html dosyanızda:

<script type="text/javascript" src="file.js"></script>
<script type="text/javascript">
   MYLIBRARY.init(["somevalue", 1, "controlId"]);
   MYLIBRARY.helloWorld();
</script>

4
@Naeem - dosya.js, MYLIBRARY.init (["somevalue", 1, "controlId"]) süresinin% 100'ü yüklendiğinde; idam mı? Belgeyi koymaya hazır bir belgeye ihtiyacımız olabilir mi?
Darius.V

2
1) MYLIBRARY varsa, onu kullanın veya yeni bir nesne tanımlayın. Amaç genel bir ad alanı oluşturmaktır, normalde alt ad alanlarını kullanacağım, böylece bu satır en üst düzey ad alanını yeniden tanımlamaktan kaçınmaya yardımcı olur. 2) Evet, bir singleton yarattı.
Naeem Sarfraz

1
Bu fikre bir örnek
verdim

1
Bu ifade ne anlama geliyor? var MYLIBRARY = MYLIBRARY || (function(){}());? Neden MYLIBRARYbir boole değerine ayarlanmalıdır?
Alex

1
@Alexander, yukarıdaki yorumuma bakın stackoverflow.com/questions/2190801/…
Naeem Sarfraz

79

Parametreleri rastgele niteliklerle geçirebilirsiniz. Bu, tüm yeni tarayıcılarda çalışır.

<script type="text/javascript" data-my_var_1="some_val_1" data-my_var_2="some_val_2" src="/js/somefile.js"></script>

Somefile.js içinde değişken değerleri şu şekilde alabilirsiniz:

........

var this_js_script = $('script[src*=somefile]'); // or better regexp to get the file name..

var my_var_1 = this_js_script.attr('data-my_var_1');   
if (typeof my_var_1 === "undefined" ) {
   var my_var_1 = 'some_default_value';
}
alert(my_var_1); // to view the variable value

var my_var_2 = this_js_script.attr('data-my_var_2');   
if (typeof my_var_2 === "undefined" ) {
   var my_var_2 = 'some_default_value';
}
alert(my_var_2); // to view the variable value

...vb...


1
Çok güzel bir çözüm, bu bile zaman uyumsuz özellik ile çalışır.
ViRuSTriNiTy

2
eski ancak bu googling için: bir CSP (içerik güvenliği politikası) üzerinde çalışmanız gerekiyorsa bu harika. Dil kaynaklarından ve API anahtarlarından vb. Belirlenen dizeleri JS dosyalarına geçirdiğimiz birçok komut dosyası kullanıyoruz.
19:24

2
Ayrıca kullanabileceğinizi unutmayın , uyumluluk için caniuse.com/#feat=document-currentscript adresinedocument.currentScript bakın (veya bir çoklu dolgu kullanın)
Yves M.

$(..)Sözdizimi dahil etmeyi unutmayın, jquery olduğunu.
Timo

48

Karşılaştığım başka bir fikir id, <script>öğeye bir atama ve argümanları data-*nitelik olarak iletmektir. Ortaya çıkan <script>etiket şuna benzer:

<script id="helper" data-name="helper" src="helper.js"></script>

Komut dosyası daha sonra kendini programlı olarak bulmak ve bağımsız değişkenleri ayrıştırmak için kimliği kullanabilir. Önceki <script>etiket göz önüne alındığında, ad şu şekilde alınabilir:

var name = document.getElementById("helper").getAttribute("data-name");

Biz name=helper


4
İd özelliğine bağlı kalmak istemiyorsanız, helper.jskomut dosyası döngünüzü scriptsayfadaki tüm etiketler arasında arayabilir, etiketini arayabilir scr="helper.js"ve sonra ayıklayabilirsiniz data-name.
jvannistelrooy

1
@jvannistelrooy Ben denemedim ama jquery ve böyle akıllı bir seçici ile senaryoya almak gerekir inanıyorum: var this_js_script = $('script[src*=somefile]');( yukarıdan kopyalandı )
LosManos

19

Bu URL'ye göz atın. İhtiyaç için mükemmel çalışıyor.

http://feather.elektrum.org/book/src.html

Yazara çok teşekkürler. Hızlı başvuru için aşağıdaki ana mantığı yapıştırdım:

var scripts = document.getElementsByTagName('script');
var myScript = scripts[ scripts.length - 1 ];

var queryString = myScript.src.replace(/^[^\?]+\??/,'');

var params = parseQuery( queryString );

function parseQuery ( query ) {
  var Params = new Object ();
  if ( ! query ) return Params; // return empty object
  var Pairs = query.split(/[;&]/);
  for ( var i = 0; i < Pairs.length; i++ ) {
    var KeyVal = Pairs[i].split('=');
    if ( ! KeyVal || KeyVal.length != 2 ) continue;
    var key = unescape( KeyVal[0] );
    var val = unescape( KeyVal[1] );
    val = val.replace(/\+/g, ' ');
    Params[key] = val;
  }
  return Params;
}

1
Bu çözümü beğendim, ancak önbellekleri bozmamak için parça tanımlayıcıyı kullanmak için biraz değiştirdim: var frag = myScript.src.replace (/ ^ [^ \ #] + \ #? /, '') ;
Mark Nottingham

Oh, ve JSON'u oraya koymanın, urlencode olduğunuz sürece işe yaradığını gördüm.
Mark Nottingham

@ user378221 - bunun her zaman doğru dosyayı alacağından emin misiniz? Yani bu dosyanın son olduğunu varsayar. Bu yürütülmeden önce daha fazla komut dosyası etiketi yüklenirse ne olur? Bu mümkün olup olmadığını bilmiyorum, ama belge kod yürütme diğer etiketleri yüklemek için bitirmek için beklemiyor varsayıyorum?
Darius.V

Kullanımı daha iyi Bu işlev kullanımdan kaldırıldığı için unescape yerine decodeURI () veya decodeURIComponent () kullanın.
Steve Childs

@ Darius.V Bu, zaman uyumsuz komut dosyaları için çalışır. Bir seçenek olarak seçenek 5 ile seçenek 1'i kullanmayı tercih ederim .
Luke

14

Global değişkenleri kullanırsınız :-D.

Bunun gibi:

<script type="text/javascript">
   var obj1 = "somevalue";
   var obj2 = "someothervalue";
</script>
<script type="text/javascript" src="file.js"></script">

'File.js' içindeki JavaScript kodu, sorunsuz obj1ve obj2sorunsuz bir şekilde erişebilir .

EDIT Sadece 'file.js' bildirmek isteyip istemediğinizi obj1ve obj2hatta bildirilmişse, aşağıdaki işlevi kullanabileceğinizi eklemek istersiniz .

function IsDefined($Name) {
    return (window[$Name] != undefined);
}

Bu yardımcı olur umarım.


Bu IE'de referans verilmeyen bir hata atar. Bu işlevin tercih edilen gövdesi return typeof window[$Name] !== 'undefined';. Bu işleve değişkenin adını içeren bir dize ileteceğinizi lütfen unutmayın. Değişkenin çağrı kodunda var olup olmadığını kontrol etmek daha kolaydır (bu bir işlev olarak uygulanamaz) if (typeof var !== 'undefined').
Anthony DiSanti

2
Asla IE kullanmayın. Afedersiniz.
NawaMan

Evet, ancak JavaScript ile ilgili deneyimlerime göre, global değişkenleri yalnızca modül ad alanları için kullanacağım ve burada gösterildiği gibi gerekli olanı (init kodu, bazı özellikler gibi) açığa çıkaracağım . Karmaşık projelerde adlandırma çatışmaları elde etmek çok kolaydır ... zamanınızı harcamak ve daha sonra değişkeni zaten projede başka bir yerde kullandığınızı öğrenmek.
Matt

Sen atlayabilirsiniz var.
Timo

12

İşte çok acele bir kavram kanıtı.

Eminim ki iyileştirmeler yapılabilecek en az 2 yer vardır ve bunun vahşi doğada uzun süre hayatta kalamayacağından da eminim. Daha sunulabilir veya kullanılabilir hale getirmek için herhangi bir geri bildirim hoş geldiniz.

Anahtar, komut dosyası öğeniz için bir kimlik belirlemektir. Tek yakalama, bu, komut dizesini sorgu dizesini çekmek için aradığı için komut dosyasını yalnızca bir kez çağırabileceğiniz anlamına gelir. Bunun yerine, komut dosyası, herhangi birinin işaret edip etmediğini görmek için tüm sorgu öğeleri arasında dolaşırsa ve bu durumda böyle bir komut dosyası öğesinin son örneğini kullanıyorsa bu sorun giderilebilir. Her neyse, şu kodla:

Komut dosyası çağrılıyor:

window.onload = function() {
//Notice that both possible parameters are pre-defined.
//Which is probably not required if using proper object notation
//in query string, or if variable-variables are possible in js.
var header;
var text;

//script gets the src attribute based on ID of page's script element:
var requestURL = document.getElementById("myScript").getAttribute("src");

//next use substring() to get querystring part of src
var queryString = requestURL.substring(requestURL.indexOf("?") + 1, requestURL.length);

//Next split the querystring into array
var params = queryString.split("&");

//Next loop through params
for(var i = 0; i < params.length; i++){
 var name  = params[i].substring(0,params[i].indexOf("="));
 var value = params[i].substring(params[i].indexOf("=") + 1, params[i].length);

    //Test if value is a number. If not, wrap value with quotes:
    if(isNaN(parseInt(value))) {
  params[i] = params[i].replace(value, "'" + value + "'");
 }

    // Finally, use eval to set values of pre-defined variables:
 eval(params[i]);
}

//Output to test that it worked:
document.getElementById("docTitle").innerHTML = header;
document.getElementById("docText").innerHTML = text;
};

Aşağıdaki sayfa aracılığıyla çağrılan komut dosyası:

<script id="myScript" type="text/javascript" 
        src="test.js?header=Test Page&text=This Works"></script>

<h1 id="docTitle"></h1>
<p id="docText"></p>

eval aslında değeri global değişken olarak ayarlayacaktır ... oldukça havalı.
rodmjay

1
eval kötü kaçıyor
Barry Chapman

@barrychapman - oh man, 2010. Orada 10 tane kırmızı bayrak olmamasına şaşırdım.
Anthony

9

çok basit olabilir

Örneğin

<script src="js/myscript.js?id=123"></script>
<script>
    var queryString = $("script[src*='js/myscript.js']").attr('src').split('?')[1];
</script>

Daha sonra aşağıdaki gibi sorgu dizesini json'a dönüştürebilirsiniz

var json = $.parseJSON('{"' 
            + queryString.replace(/&/g, '","').replace(/=/g, '":"') 
            + '"}');

ve sonra gibi kullanabilirsiniz

console.log(json.id);

6

JQuery gibi bir Javascript çerçevesi kullanıyorsanız bu kolayca yapılabilir. Bunun gibi,

var x = $('script:first').attr('src'); //Fetch the source in the first script tag
var params = x.split('?')[1]; //Get the params

Şimdi bu parametreleri değişken parametreleriniz olarak bölerek kullanabilirsiniz.

Aynı işlem herhangi bir çerçeve olmadan yapılabilir, ancak daha fazla kod satırı alacaktır.


2
ParseQuery adında bir jQuery eklentisi de var, bunu daha da kolay hale getiriyor: plugins.jquery.com/project/parseQuery
Jimmy Cuadra

@JimmyCuadra - maalesef sağladığınız bağlantı koptu. Ancak jQuery'de
Matt

1

Javascript dosyasının komut dosyası dillerinden herhangi biri tarafından oluşturulmasını sağlayarak her isteğinizde değişkenlerinizi dosyaya enjekte edebilirsiniz. Web sunucunuza js dosyalarını statik olarak temizlememesini söylemelisiniz (mod_rewrite kullanmak yeterli olacaktır).

Sürekli değiştirildiklerinden bu js dosyalarının önbelleğini kaybettiğinizi unutmayın.

Hoşçakal.


1
Bunun neden reddedildiğini anlayamıyorum. Sunucu tarafındaki mantığa uygun, mükemmel geçerli bir çözümdür. Gördüğüm kadarıyla, OP tam bir javascript çözümü olmasını gerektirmiyor.
Anoyz

@aefxx - Haklısın. <script>Bloğun içinde, MyModule.Initialize( '<%: Model.SomeProperty%>', '<%: Model.SomeOtherProperty%>', ...);sunucuda oluşturulmuş gibi bir şey kullanabilirsiniz . Dikkat: <%:değer kaçar <%=, değer kaçmaz. MyModulebir ad alanı (yani .js dosyasının içinde kendi kendine çağrılan ve işlevi gösteren bir değişken Initialize) olur. Cevabınızı iptal ettim, çünkü bu yararlı bir katkı.
Matt

Not: nasıl daha ayrıntılı olarak açıklanmıştır açıktaki özelliği içeren bir Modülü oluşturmak için konsept, burada bu sayfada.
Matt

1

Güzel bir soru ve yaratıcı cevaplar ama benim önerim yöntemlerinizi paramterize etmek ve tüm sorunlarınızı hile yapmadan çözmeniz.

Eğer fonksiyonunuz varsa:

function A()
{
    var val = external_value_from_query_string_or_global_param;
}

bunu şu şekilde değiştirebilirsiniz:

function B(function_param)
{
    var val = function_param;
}

Bunun en doğal yaklaşım olduğunu düşünüyorum, 'dosya parametreleri' hakkında fazladan belge oluşturmanıza gerek yok ve aynı şeyi alıyorsunuz. Bu, diğer geliştiricilerin js dosyanızı kullanmasına izin verirseniz özellikle yararlıdır.


0

Hayır, bunu JS dosya URL'sinin querystring bölümüne değişkenler ekleyerek gerçekten yapamazsınız. Sizi rahatsız eden dizeyi ayrıştırmak için kod kısmını yazıyorsa, belki de başka bir yol değişkenlerinizi kodlamak ve etiketin rel niteliği gibi bir şeye koymaktır? Çok endişelendiğiniz bir şey varsa, bunun HTML doğrulaması açısından ne kadar geçerli olduğunu bilmiyorum. Sonra sadece betiğin rel özniteliğini bulmanız ve ardından json_decode.

Örneğin

<script type='text/javascript' src='file.js' rel='{"myvar":"somevalue","anothervar":"anothervalue"}'></script>

2
Bunu sahte sorgu dizesi ile yapabilirsiniz. Bu iyi bir fikir değil. Ama bu da değil. Rel niteliği, rastgele verileri bir komut dosyası etiketine sıkıştırmak yerine bir tür bağlantı ilişkisi belirtmek içindir.
Matthew Flaschen

1
^ ^ kabul etti. Sadece olduğu gibi bırakarak herhangi bir sorun göremiyorum ve <script> var obj1 = "somevalue" </script> yaklaşımını kullanarak, en iyi yolu ve inanıyorum - doğru yol.
Dal Hundal

0

Geçerli html (sanmıyorum) değil, ancak web sayfanızdaki komut dosyası etiketi için özel bir özellik oluşturursanız çalışır gibi görünüyor :

<script id="myScript" myCustomAttribute="some value" ....>

Ardından javascript'teki özel özniteliğe erişin:

var myVar = document.getElementById( "myScript" ).getAttribute( "myCustomAttribute" );

Bunun komut dosyası kaynak dizesini ayrıştırmaktan daha iyi veya kötü olduğundan emin değilim.


0

CSP kontrolünden geçen (güvenli olmayan satırları yasaklayan) bir yola ihtiyacınız varsa, hem komut dosyasına hem de CSP yönergesine benzersiz bir değer eklemek veya değerlerinizi html'ye yazmak ve tekrar okumak için nonce yöntemini kullanmanız gerekir.

Express.js için nonce yöntemi:

const uuidv4 = require('uuid/v4')

app.use(function (req, res, next) {
  res.locals.nonce = uuidv4()
  next()
})

app.use(csp({
  directives: {
    scriptSrc: [
      "'self'",
      (req, res) => `'nonce-${res.locals.nonce}'`  // 'nonce-614d9122-d5b0-4760-aecf-3a5d17cf0ac9'
    ]
  }
}))

app.use(function (req, res) {
  res.end(`<script nonce="${res.locals.nonce}">alert(1 + 1);</script>`)
})

veya html yöntemine değerler yazın. bu durumda Jquery kullanarak:

<div id="account" data-email="{{user.email}}"></div>
...


$(document).ready(() => {
    globalThis.EMAIL = $('#account').data('email');
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.