Dynamicznie dodaj tag skryptu za pomocą src, który może zawierać dokument.write


160

Chcę dynamicznie dołączyć tag skryptu do strony internetowej, ale nie mam kontroli nad jego src, więc src = "source.js" może wyglądać tak.

document.write('<script type="text/javascript">')
document.write('alert("hello world")')
document.write('</script>')
document.write('<p>goodbye world</p>')

Teraz zwykle kładąc

<script type="text/javascript" src="source.js"></script> 

w głowie działa dobrze, ale czy jest jakiś inny sposób na dynamiczne dodawanie source.js przy użyciu czegoś takiego jak innerHTML?

jsfiddle tego, co próbowałem


2
po godzinach zmagań z postami jest rozwiązaniem! https://github.com/krux/postscribe/
Cadell Christo

Odpowiedzi:


210
var my_awesome_script = document.createElement('script');

my_awesome_script.setAttribute('src','http://example.com/site.js');

document.head.appendChild(my_awesome_script);

94

Możesz użyć tej document.createElement()funkcji w następujący sposób:

function addScript( src ) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  document.body.appendChild( s );
}

Jak zrobiłbyś to asynchroniczne?
UKDataGeek

3
@mobile bloke: s.async = true;
axlotl

s.setAttribute ('src', src); może być s.src src = (myślę?) Wiem, że to nie jest PCG
Brandito

67

Jest onloadfunkcja, którą można wywołać po pomyślnym załadowaniu skryptu:

function addScript( src,callback) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  s.onload=callback;
  document.body.appendChild( s );
}

Nauczyłem się czegoś nowego. Miły!
mix3d

16

ładny mały skrypt, który napisałem, aby załadować wiele skryptów:

function scriptLoader(scripts, callback) {

    var count = scripts.length;

    function urlCallback(url) {
        return function () {
            console.log(url + ' was loaded (' + --count + ' more scripts remaining).');
            if (count < 1) {
                callback();
            }
        };
    }

    function loadScript(url) {
        var s = document.createElement('script');
        s.setAttribute('src', url);
        s.onload = urlCallback(url);
        document.head.appendChild(s);
    }

    for (var script of scripts) {
        loadScript(script);
    }
};

stosowanie:

scriptLoader(['a.js','b.js'], function() {
    // use code from a.js or b.js
});

2
Przepraszamy ... właśnie znalazłem lepszy, który zezwala na zależności stackoverflow.com/a/1867135/678780
EliSherer

5

Możesz spróbować wykonać następujący fragment kodu.

function addScript(attribute, text, callback) {
    var s = document.createElement('script');
    for (var attr in attribute) {
        s.setAttribute(attr, attribute[attr] ? attribute[attr] : null)
    }
    s.innerHTML = text;
    s.onload = callback;
    document.body.appendChild(s);
}

addScript({
    src: 'https://www.google.com',
    type: 'text/javascript',
    async: null
}, '<div>innerHTML</div>', function(){});

4

To jest praca dla mnie.

Możesz to sprawdzić.

var script_tag = document.createElement('script');
script_tag.setAttribute('src','https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js');
document.head.appendChild(script_tag);
window.onload = function() {
    if (window.jQuery) {  
        // jQuery is loaded  
        alert("ADD SCRIPT TAG ON HEAD!");
    } else {
        // jQuery is not loaded
        alert("DOESN'T ADD SCRIPT TAG ON HEAD");
    }
}


3

Gdy skrypty są ładowane asynchronicznie, nie mogą wywoływać document.write. Połączenia zostaną po prostu zignorowane, a na konsoli zostanie wyświetlone ostrzeżenie.

Możesz użyć następującego kodu, aby dynamicznie załadować skrypt:

var scriptElm = document.createElement('script');
scriptElm.src = 'source.js';
document.body.appendChild(scriptElm);

To podejście działa dobrze tylko wtedy, gdy źródło należy do oddzielnego pliku.

Ale jeśli masz kod źródłowy jako funkcje wbudowane, które chcesz ładować dynamicznie i chcesz dodać inne atrybuty do tagu skryptu, np. Klasa, typ itp., Pomoże Ci następujący fragment kodu:

var scriptElm = document.createElement('script');
scriptElm.setAttribute('class', 'class-name');
var inlineCode = document.createTextNode('alert("hello world")');
scriptElm.appendChild(inlineCode); 
target.appendChild(scriptElm);

2

Cóż, istnieje wiele sposobów na dołączenie dynamicznego javascript, używam tego w wielu projektach.

var script = document.createElement("script")
script.type = "text/javascript";
//Chrome,Firefox, Opera, Safari 3+
script.onload = function(){
console.log("Script is loaded");
};
script.src = "file1.js";
document.getElementsByTagName("head")[0].appendChild(script);

Możesz wywołać funkcję create uniwersalną, która pomoże ci załadować dowolną liczbę plików javascript. Tutaj znajduje się pełny tutorial na ten temat.

Wstawianie dynamicznego JavaScript we właściwy sposób


2
fyi, link nie działa, nie mogłem znaleźć artykułu w innym miejscu.
user1063287

1

Jedynym sposobem na to jest zastąpienie document.writewłasnej funkcji, która będzie dodawać elementy na dole strony. Z jQuery jest całkiem proste:

document.write = function(htmlToWrite) {
  $(htmlToWrite).appendTo('body');
}

Jeśli masz kod HTML trafiający do document.write fragmentami, jak w przykładzie pytania, musisz buforować htmlToWritesegmenty. Może coś takiego:

document.write = (function() {
  var buffer = "";
  var timer;
  return function(htmlPieceToWrite) {
    buffer += htmlPieceToWrite;
    clearTimeout(timer);
    timer = setTimeout(function() {
      $(buffer).appendTo('body');
      buffer = "";
    }, 0)
  }
})()

1

Wypróbowałem to, dołączając rekursywnie każdy skrypt

Uwaga Jeśli twoje skrypty są zależne jeden po drugim, pozycja będzie musiała być zsynchronizowana.

Zależność główna powinna znajdować się na końcu tablicy, aby początkowe skrypty mogły z niej korzystać

const scripts = ['https://www.gstatic.com/firebasejs/6.2.0/firebase-storage.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-firestore.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-app.js']
let count = 0

  
 const recursivelyAddScript = (script, cb) => {
  const el = document.createElement('script')
  el.src = script
  if(count < scripts.length) {
    count ++
    el.onload = recursivelyAddScript(scripts[count])
    document.body.appendChild(el)
  } else {
    console.log('All script loaded')
    return
  }
}
 
  recursivelyAddScript(scripts[count])


1

Wczytuje skrypty zależne od siebie we właściwej kolejności.

Oparty na odpowiedzi Satyama Pathaka , ale naprawiono obciążenie. Został uruchomiony przed załadowaniem skryptu.

const scripts = ['https://www.gstatic.com/firebasejs/6.2.0/firebase-storage.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-firestore.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-app.js']
let count = 0

  
 const recursivelyAddScript = (script, cb) => {
  const el = document.createElement('script')
  el.src = script
  if(count < scripts.length) {
    count ++
    el.onload = () => recursivelyAddScript(scripts[count])
    document.body.appendChild(el)
  } else {
    console.log('All script loaded')
    return
  }
}
 
  recursivelyAddScript(scripts[count])


0

Oto zminimalizowany fragment, ten sam kod, którego używa Google Analytics i Facebook Pixel:

!function(e,s,t){(t=e.createElement(s)).async=!0,t.src="https://example.com/foo.js",(e=e.getElementsByTagName(s)[0]).parentNode.insertBefore(t,e)}(document,"script");

Zastąp https://example.com/foo.jsścieżką do skryptu.


0

Jedna linijka (jednak bez istotnej różnicy w stosunku do odpowiedzi powyżej):

document.body.appendChild(document.createElement('script')).src = 'source.js';
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.