<script> öğesi eklenemiyor


276

Aşağıdaki kod parçasının neden script öğesini DOM'ye eklemediğine dair bir fikriniz var mı?

var code = "<script></script>";
$("#someElement").append(code);

4
"çalışmıyor" tanımlayın - ama ben sorun komut dosyaları dom ağacının bir parçası değildir şüpheli.
Joel Coehoorn

1
Bahse girerim, komut dosyası düğümünün DOM'a eklenmesi, ancak tarayıcının komut dosyasını yürütmemesi.
Yasadışı Programcı

Dan, bunu gerçekten nasıl test ettin?
James

1
@Joel - "çalışmıyor" = herhangi bir etkisi yok, yani kod içindeki kod çalıştırılmamış @Outlaw Programcı - düğüm DOM @Jimmy'ye eklenmez Evet, test ettim ve çalışmıyor
Dan Burzo

Yanıtlar:


259

Bazı tarayıcıların doğrudan yaptığınızda bazı değişikliklere saygı duymadığı (kod etiketi ile denediğiniz gibi metinden HTML oluşturduğum), ancak yerleşik komutlarla yaptığınız sorunlar gördüm işler daha iyi. Bunu dene:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

Gönderen: jQuery için JSON


18
<script> etiketinin mevcut bir öğenin innerHTML'sine değil DOM'un kendisine eklenmesi gerekir.
Diodeus - James MacFarlane

6
@Diodeus innerHTML DOM'nin bir parçasıdır ve tarayıcı tarafından anında ayrıştırılır, bu nedenle bu geçerli bir durumdur.
Cristian Toma


5
Öğenin DOM'de gerçekten görünmesini istiyorsanız, jQuery'nin ekini kullanmayın. Bunu başarmak için yerel appendChild kullanın.
Minqi Pan

8
$("#someElement")[0].appendChild( script );
Minqi Pan

352

İyi Haber:

% 100 çalışıyor.

Komut dosyası etiketinin içine bir şey eklemeniz yeterlidir alert('voila!');. Belki de "Neden DOM'da görmedim?" Diye sormak isteyebileceğiniz doğru soru. .

Karl Swedberg, jQuery API sitesindeki ziyaretçinin yorumuna güzel bir açıklama yaptı . Ben yok , doğrudan okuyabilir tüm sözlerini tekrarlamak istiyorum orada burada (ı yorumlarla arasında gezinmek için sert orada bulunan) .

JQuery'nin tüm ekleme yöntemleri, DOM'ye yerleştirilmeden önce ve sonra öğeleri temizlemek / işlemek için domManip işlevini dahili olarak kullanır. DomManip işlevinin yaptığı şeylerden biri, eklenecek komut dosyası öğelerini dışarı çıkarmak ve bunları DOM parçasının geri kalanıyla enjekte etmek yerine "evalScript yordamı" ile çalıştırmaktır. Komut dosyalarını ayrı olarak ekler, değerlendirir ve daha sonra DOM'dan kaldırır.

JQuery'nin bunu yapmasının nedenlerinden birinin, belirli koşullar altında komut dosyaları eklerken Internet Explorer'da oluşabilecek "İzin Reddedildi" hatalarından kaçınmak olduğuna inanıyorum. Ayrıca, eklediğiniz bir kapsayıcı öğenin içindeyse ve daha sonra DOM içinde gezinirken aynı komut dosyasını (sorunlara neden olabilecek) tekrar tekrar eklemekten / değerlendirmekten kaçınır.

Bir sonraki şey, .append()bir komut dosyası eklemek için işlevi kullanarak kötü haberlerin ne olduğunu özetleyeceğim .


Ve Kötü Haber ..

Kodunuzda hata ayıklama yapamazsınız.

Şaka yapmıyorum, debugger;kesme noktası olarak ayarlamak istediğiniz satır arasına anahtar kelime ekleseniz bile , kaynak koddaki kesme noktasını görmeden yalnızca nesnenin çağrı yığınını elde edersiniz ( anahtar kelime yalnızca webkit tarayıcısında çalışır, diğer tüm büyük tarayıcılar bu anahtar kelimeyi atlamış gibi görünür) .

Kodunuzun ne yaptığını tam olarak anlarsanız, bunun küçük bir dezavantajı olacaktır. Ancak bunu yapmazsanız, debugger;yalnızca (veya benim) kodunuzda neyin yanlış olduğunu bulmak için her yere bir anahtar kelime ekleyeceksiniz . Her neyse, bir alternatif var, javascript'in yerel olarak HTML DOM'yi değiştirebileceğini unutmayın.


Geçici çözüm.

HTML DOM'yi değiştirmek için javascript (jQuery değil) kullanın

Hata ayıklama yeteneğini kaybetmek istemiyorsanız, javascript yerel HTML DOM manipülasyonunu kullanabilirsiniz. Bu örneği düşünün:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

Orada, tıpkı eski günlerde olduğu gibi değil. Ve bellek sızıntılarını önlemek için artık başvurulmayan ve artık gerekli olmayan tüm nesneler için DOM'da veya bellekte olan şeyleri temizlemeyi unutmayın. İşleri temizlemek için bu kodu düşünebilirsiniz:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

Bu geçici çözümün dezavantajı, yanlışlıkla yinelenen bir komut dosyası ekleyebilmenizdir ve bu kötüdür. Buradan .append(), eklemeden önce bir nesne doğrulaması ekleyerek ve komut dosyasını eklendikten hemen sonra DOM'dan kaldırarak işlevi biraz taklit edebilirsiniz . Bu örneği düşünün:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

Bu şekilde, komut dosyası yinelemesinden koruyarak hata ayıklama özelliğine sahip komut dosyası ekleyebilirsiniz. Bu sadece bir prototip, olmasını istediğiniz her şey için genişletebilirsiniz. Bu yaklaşımı kullanıyorum ve bundan oldukça memnunum. Tabii ki ben .append()bir komut dosyası eklemek için asla jQuery kullanmaz .


2
Harika bir açıklama, teşekkürler! Peki "UnusedReferencedObjects" miydi?
acme

Teşekkürler. Yüklediğiniz komut dosyasında oluşturduğunuz herhangi bir nesne olması gereken "UnusedReferencedObjects" in ilk oluşumuna atıfta bulunduğunuzu varsayıyorum. DeleteObject işlevinin ne yaptığını görürseniz daha iyi anlarsınız, işleve ilettiğiniz herhangi bir nesneyi silersiniz. Net olmak için kodda biraz yorum ekleyeceğim. :)
Hendra Uzia

Süper gönderi! ACrosman örneği benim için çalışmadı ve yazınızı hazırladıktan sonra $ ("# someElement") yerine geçtim. Append (script); $ ("# someElement") [0] .appendChild (kod) ile; Hangi düzeltti :) Açıklama için Thnx
Maarten Kieft

7
$.getScriptjQuery içine yerleştirilmiştir.
zzzzBov

SourceURL'ler ( blog.getfirebug.com/2009/08/11/… ) hata ayıklama sorunlarına yardımcı olabilir.
vsevik

23

JQuery işlevini kullanarak bir JavaScript dosyasını dinamik olarak yüklemek mümkündürgetScript

$ .getScript ('http://www.whatever.com/shareprice/shareprice.js', işlev () {
  Display.sharePrice ();
});

Şimdi harici komut dosyası çağrılır ve yüklenemezse nazikçe bozulur.


7
Bu, DOM'ye hiçbir şey eklemez. Çağırır eval().
nh2

20

Ne demek "çalışmıyor"?

jQuery, bir SCRIPT öğesi oluşturmaya çalıştığınızı algılar ve öğenin içeriğini otomatik olarak genel bağlam içinde çalıştırır. Bana bunun işe yaramadığını mı söylüyorsun? -

$('#someElement').append('<script>alert("WORKING");</script>');

Düzenleme: jQuery, dediğim gibi, kodu çalıştıracak ve sonra SCRIPT öğesini silecek çünkü komutu çalıştırdıktan sonra DOM (örneğin Firebug içinde) SCRIPT öğesi görmüyorsanız - Ben SCRIPT öğeleri inanıyorum vücuda her zaman eklenir ... ama yine de - yerleştirme bu durumda kod yürütme üzerinde kesinlikle hiçbir etkisi yoktur.


17

Bu çalışıyor:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

Görünüşe göre jQuery komut dosyaları ile akıllıca bir şey yapıyor, bu yüzden jQuery nesnesi yerine html öğesini eklemeniz gerekiyor.


2
Bu benim durumumda çalışan tek çözüm. Yukarıdaki diğer sollar html dosyasında önceden mevcut olan javascript koduna bağlıdır. Dinamik olarak kod eklediğimden, bu tür javascript kodu önceden bilinemez! TEŞEKKÜRLER Darwin!
tgoneil

14

Bu yardımcı olabilir deneyin:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

9
neden bu adam negatifler hiçbir fikrim yok her şey için jquery kullanmaya devam etmek için yeterince aptal değil!
SSpoke

Muhtemelen cevapların çoğu jQuery kullanır çünkü soruda OP jQuery kullanıyor.
sanbor

3

Ben aynı şeyi yapmak istiyorum ama diğer çerçeveye bir komut dosyası etiketi eklemek için!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);

3
<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

</script>Dize sona erdiği tüm komut, içinde bunu önlemek "</scr" + "ipt>"yerine kullanılabilir.


Veya javascript'inizi doğrudan HTML belgesine gömmeyin. Harici komut dosyalarında bu sorun yoktur.
Ian Clelland

Dizileri kaçış: "\x3cscript\x3e\x3c/script\x3e". XHTML'de yalnızca yorum yapılmamış bir CDATA bloğu koymanız gerekir.
Eli Gray

2
Daha ziyade </buna izin verilmiyor. Bkz. Stackoverflow.com/questions/236073/…
Gumbo


1

Senaryonuz yürütülüyor, document.writeondan kullanamazsınız . Test etmek ve kullanmaktan kaçınmak için bir uyarı kullanın document.write. İle js dosyanızın ifadeleri document.writeyürütülmez ve işlevin geri kalanı yürütülür.


1

Bence en iyi çözüm bu. Google Analytics bu şekilde enjekte edilir.

var (function(){
    var p="https:" == document.location.protocol ? "https://" : "http://";
        d=document,
        g=d.createElement('script'),
        s=d.getElementsByTagName('script')[0];
        g.type='text/javascript';
        g.src=p+'url-to-your-script.js';
        s.parentNode.insertBefore(g,s); })();

1

Komut Dosyası DOM Öğesi oluşturmak için jQuery'ye ihtiyacınız yoktur . Vanilya ES6 ile şu şekilde yapılabilir:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

Bir içine sarılmasına gerek yoktur Promise, ancak bunu yaparak komut dosyası yüklendiğinde vaatleri çözmenize izin verir ve uzun süren komut dosyaları için yarış koşullarını önlemeye yardımcı olur.


0

Gövdeye komut dosyası ekle:

$(document).ready(function() {
    $("<script>", {  src : "bootstrap.min.js",  type : "text/javascript" }).appendTo("body");
});

0

Kod eklemek istiyorsanız bunu yapmanın başka bir yolu document.createElementyöntemi kullanmaktır, ancak .innerHTMLyerine kullanmaktır .src.

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );

0

Bunu denedim biri ve eserleri cezası. Sadece <sembolü değiştirin \x3C.

// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);

veya

//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");

Kodu burada test edebilirsiniz .


0

Böyle deneyebilirim

var code = "<script></" + "script>";
$("#someElement").append(code);

Yapamamanızın tek nedeni "<script></script>", dize javascript içinde izin verilmiyor, çünkü DOM katmanı js ve HTML'nin ne olduğunu ayrıştıramıyor.


0

Komut dosyası etiketleri dahilnpm bir HTML dizesi almanıza ve komut dosyalarını yürütürken bir kaba eklemenize izin veren bir paket yazdım

Misal:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

Burada bulabilirsiniz: https://www.npmjs.com/package/appendhtml


-1

Sadece jQuery ile ayrıştırarak bir öğe oluşturun.

<div id="someElement"></div>
<script>
    var code = "<script>alert(123);<\/script>";
    $("#someElement").append($(code));
</script>

Çalışma örneği: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz


Bu hala aynı soruna sahip, bazı tarayıcılar buna saygı duymuyor.
Martin Massera

Hangi tarayıcıları ve hangi jQuery sürümünü kullandığınızı bize bildirir misiniz? Teşekkürler!
sanbor
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.