Agregue dinámicamente la etiqueta de script con src que puede incluir document.write

161

Quiero incluir dinámicamente una etiqueta de script en una página web, sin embargo, no tengo control de su src, por lo que src = "source.js" puede verse así.

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

Ahora poniendo ordinariamente

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

en la cabeza funciona bien, pero ¿hay alguna otra manera de agregar source.js dinámicamente usando algo como innerHTML?

jsfiddle de lo que he intentado

Cadell Christo
fuente
2
¡Después de horas de lucha contra la suscripción es la solución! https://github.com/krux/postscribe/
Cadell Christo
Posible duplicado de carga asincrónica de javascript con document.write
Michał Perłakowski

Respuestas:

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

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

document.head.appendChild(my_awesome_script);
dmp
fuente
94

Puede usar la document.createElement()función de esta manera:

function addScript( src ) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  document.body.appendChild( s );
}
Sirko
fuente
¿Cómo harías esto asíncrono?
UKDataGeek
3
@mobile bloke: s.async = true;
axlotl
s.setAttribute ('src', src); podría ser s.src = src (¿creo?) Sé que esto no es PCG
Brandito
68

Existe la onloadfunción, que podría llamarse cuando el script se ha cargado correctamente:

function addScript( src,callback) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  s.onload=callback;
  document.body.appendChild( s );
}
MSS
fuente
1
Aprendí algo nuevo. ¡Agradable!
mix3d
16

escribí un pequeño guión para cargar varios guiones:

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

uso:

scriptLoader(['a.js','b.js'], function() {
    // use code from a.js or b.js
});
EliSherer
fuente
2
Lo siento ... acabo de encontrar uno mejor que permita dependencias stackoverflow.com/a/1867135/678780
EliSherer
5

Puede intentar seguir el fragmento de código.

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(){});
vaenow
fuente
4

Esto es trabajo para mí.

Usted puede comprobarlo.

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

jd savaj
fuente
3

Cuando los scripts se cargan de forma asíncrona, no pueden llamar a document.write. Las llamadas simplemente serán ignoradas y se escribirá una advertencia en la consola.

Puede usar el siguiente código para cargar el script dinámicamente:

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

Este enfoque funciona bien solo cuando su fuente pertenece a un archivo separado.

Pero si tiene el código fuente como funciones en línea que desea cargar dinámicamente y desea agregar otros atributos a la etiqueta del script, por ejemplo, clase, tipo, etc., el siguiente fragmento lo ayudaría:

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

Bueno, hay varias formas de incluir JavaScript dinámico. Utilizo este para muchos de los proyectos.

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

Puede llamar a crear una función universal que puede ayudarlo a cargar tantos archivos javascript como sea necesario. Hay un tutorial completo sobre esto aquí.

Insertar Javascript dinámico de la manera correcta

Shubham Maurya
fuente
2
digo, el enlace no funciona, no pude encontrar el artículo en otro lugar.
user1063287
1

la única forma de hacerlo es reemplazarlo document.writecon su propia función que agregará elementos al final de su página. Es bastante sencillo con jQuery:

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

Si tiene html llegando a document.write en fragmentos como el ejemplo de la pregunta, necesitará almacenar en búfer los htmlToWritesegmentos. Tal vez algo como esto:

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

Lo intenté agregando recursivamente cada secuencia de comandos

Nota Si sus scripts dependen uno tras otro, entonces la posición deberá estar sincronizada.

La dependencia mayor debe estar en el último lugar de la matriz para que los scripts iniciales puedan usarla

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

Satyam Pathak
fuente
1

Carga scripts que dependen unos de otros en el orden correcto.

Basado en la respuesta de Satyam Pathak , pero reparó la carga. Se activó antes de que el script se cargara realmente.

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

kolorafa
fuente
0

Aquí hay un fragmento reducido, el mismo código que utiliza Google Analytics y 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");

Reemplace https://example.com/foo.jscon su ruta de script.

Moshe Simantov
fuente
0

Una frase (sin embargo, no hay una diferencia esencial con las respuestas anteriores):

document.body.appendChild(document.createElement('script')).src = 'source.js';
JohnW
fuente