Fügen Sie dynamisch ein Skript-Tag mit src hinzu, das document.write enthalten kann


160

Ich möchte ein Skript-Tag dynamisch in eine Webseite einfügen, habe jedoch keine Kontrolle über dessen src, sodass src = "source.js" möglicherweise so aussieht.

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

Jetzt normalerweise setzen

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

im Kopf funktioniert gut, aber gibt es eine andere Möglichkeit, source.js dynamisch mit so etwas wie innerHTML hinzuzufügen?

jsfiddle von dem, was ich versucht habe


2
Nach stundenlangem Kampf ist das Nachschreiben die Lösung! https://github.com/krux/postscribe/
Cadell Christo

Antworten:


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

Sie können die document.createElement()Funktion folgendermaßen verwenden:

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

Wie würden Sie diesen Async machen?
UKDataGeek

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

s.setAttribute ('src', src); könnte sein s.src = src (ich denke?) Ich weiß, das ist nicht pcg
Brandito

67

Es gibt die onloadFunktion, die aufgerufen werden kann, wenn das Skript erfolgreich geladen wurde:

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

Etwas Neues gelernt. Nett!
mix3d

16

Ein nettes kleines Skript, das ich geschrieben habe, um mehrere Skripte zu laden:

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);
    }
};

Verwendung:

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

2
Sorry ... habe gerade eine bessere gefunden, die Abhängigkeiten zulässt stackoverflow.com/a/1867135/678780
EliSherer

5

Sie können versuchen, das folgende Code-Snippet zu verwenden.

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

Das ist Arbeit für mich.

Du kannst es überprüfen.

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

Wenn Skripte asynchron geladen werden, können sie document.write nicht aufrufen. Die Anrufe werden einfach ignoriert und eine Warnung wird an die Konsole geschrieben.

Sie können den folgenden Code verwenden, um das Skript dynamisch zu laden:

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

Dieser Ansatz funktioniert nur dann gut, wenn Ihre Quelle zu einer separaten Datei gehört.

Wenn Sie jedoch Quellcode als Inline-Funktionen haben, die Sie dynamisch laden und dem Skript-Tag andere Attribute hinzufügen möchten, z. B. Klasse, Typ usw., hilft Ihnen das folgende Snippet:

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

2

Nun, es gibt mehrere Möglichkeiten, wie Sie dynamisches Javascript einbinden können. Ich verwende dieses für viele Projekte.

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);

Sie können create eine universelle Funktion aufrufen, mit der Sie so viele Javascript-Dateien wie nötig laden können. Hier finden Sie ein vollständiges Tutorial dazu.

Dynamisches Javascript richtig einfügen


2
Zu Ihrer Information, Link funktioniert nicht, ich konnte den Artikel nicht woanders finden.
user1063287

1

Die einzige Möglichkeit, dies zu tun, besteht darin, sie document.writedurch eine eigene Funktion zu ersetzen, mit der Elemente am Ende Ihrer Seite angehängt werden. Mit jQuery ist das ziemlich einfach:

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

Wenn HTML in document.write in Blöcken wie im Fragenbeispiel angezeigt wird, müssen Sie die htmlToWriteSegmente puffern . Vielleicht so etwas:

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

1

Ich habe es versucht, indem ich jedes Skript rekursiv angehängt habe

Hinweis Wenn Ihre Skripte nacheinander abhängig sind, muss die Position synchron sein.

Die Hauptabhängigkeit sollte im Array als letztes vorhanden sein, damit die ersten Skripte sie verwenden können

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

Lädt voneinander abhängige Skripte mit der richtigen Reihenfolge.

Basierend auf der Antwort von Satyam Pathak , aber die Onload wurde behoben. Es wurde ausgelöst, bevor das Skript tatsächlich geladen wurde.

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

Hier ist ein minimiertes Snippet, der den gleichen Code wie Google Analytics und Facebook Pixel verwendet:

!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");

Ersetzen Sie https://example.com/foo.jsdurch Ihren Skriptpfad.


0

Ein Einzeiler (kein wesentlicher Unterschied zu den obigen Antworten):

document.body.appendChild(document.createElement('script')).src = 'source.js';
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.