เพิ่มแท็กสคริปต์แบบไดนามิกด้วย src ที่อาจรวม document.write


161

ฉันต้องการรวมแท็กสคริปต์ในหน้าเว็บแบบไดนามิก แต่ฉันไม่สามารถควบคุมได้ว่าเป็น src ดังนั้น src = "source.js" อาจมีลักษณะเช่นนี้

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

ปกติแล้วการวาง

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

ในหัวทำงานได้ดี แต่มีวิธีอื่นที่ฉันสามารถเพิ่ม source.js แบบไดนามิกโดยใช้สิ่งที่ต้องการ InnerHTML?

jsfiddle ของสิ่งที่ฉันได้ลอง


2
หลังจากหลายชั่วโมงของการโพสต์การดิ้นรนเป็นวิธีการแก้! https://github.com/krux/postscribe/
Cadell Christo

คำตอบ:


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

คุณสามารถใช้document.createElement()ฟังก์ชั่นเช่นนี้:

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

คุณจะทำ async นี้อย่างไร
UKDataGeek

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

s.setAttribute ('src', src); อาจเป็น s.src = src (ฉันคิดว่า?) ฉันรู้ว่านี่ไม่ใช่ pcg
Brandito

68

มีonloadฟังก์ชันที่สามารถเรียกใช้เมื่อสคริปต์โหลดสำเร็จ:

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

1
เรียนรู้สิ่งใหม่ ๆ ดี!
mix3d

16

สคริปต์เล็ก ๆ ที่ดีที่ฉันเขียนเพื่อโหลดหลายสคริปต์:

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

การใช้งาน:

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

2
ขออภัย ... เพิ่งค้นพบสิ่งที่ดีกว่าที่อนุญาตการพึ่งพาstackoverflow.com/a/1867135/678780
EliSherer

5

คุณสามารถลองโค้ดต่อไปนี้

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

นี่คือผลงานสำหรับฉัน

คุณสามารถตรวจสอบได้

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

เมื่อสคริปต์ถูกโหลดแบบอะซิงโครนัสจะไม่สามารถเรียก document.write ได้ การโทรจะถูกเพิกเฉยและคำเตือนจะถูกเขียนลงในคอนโซล

คุณสามารถใช้รหัสต่อไปนี้เพื่อโหลดสคริปต์แบบไดนามิก:

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

วิธีนี้ใช้ได้ดีเมื่อแหล่งที่มาของคุณเป็นไฟล์แยกต่างหาก

แต่ถ้าคุณมีซอร์สโค้ดเป็นฟังก์ชั่นอินไลน์ซึ่งคุณต้องการโหลดแบบไดนามิกและต้องการเพิ่มคุณสมบัติอื่น ๆ ลงในแท็กสคริปต์เช่น class, type, etc. จากนั้น 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

มีหลายวิธีที่คุณสามารถรวมจาวาสคริปต์แบบไดนามิกฉันใช้อันนี้กับหลายโครงการ

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

คุณสามารถเรียกสร้างฟังก์ชั่นสากลที่สามารถช่วยคุณโหลดไฟล์จาวาสคริปต์ได้มากเท่าที่ต้องการ มีการสอนแบบเต็มเกี่ยวกับที่นี่

การแทรก Javascript แบบไดนามิกในวิธีที่ถูกต้อง


2
fyi, ลิงค์ไม่ทำงานฉันไม่พบบทความอื่น
user1063287

1

วิธีเดียวในการทำเช่นนี้คือแทนที่document.writeด้วยฟังก์ชั่นของคุณเองซึ่งจะผนวกองค์ประกอบไว้ที่ด้านล่างของหน้า มันตรงไปตรงมากับ jQuery:

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

หากคุณมี html มาที่ document.write เป็นชิ้น ๆ เช่นตัวอย่างคำถามคุณจะต้องบัฟเฟอร์htmlToWriteเซ็กเมนต์ อาจจะเป็นสิ่งนี้:

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

1

ฉันลองใช้งานด้วยการต่อท้ายแต่ละสคริปต์ซ้ำ

หมายเหตุหากสคริปต์ของคุณขึ้นต่อกันตำแหน่งจะต้องมีการซิงค์

Major Dependency ควรอยู่ในอาร์เรย์สุดท้ายเพื่อให้สคริปต์เริ่มต้นสามารถใช้งานได้

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

โหลดสคริปต์ที่ขึ้นอยู่กับลำดับที่ถูกต้อง

ขึ้นอยู่กับการตอบสนองของSatyam Pathakแต่แก้ไขการโหลด มันถูกเรียกใช้ก่อนที่สคริปต์จะโหลดจริง

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

นี่คือข้อมูลโค้ดย่อขนาดโค้ดเดียวกับ Google Analytics และ 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");

แทนที่https://example.com/foo.jsด้วยพา ธ สคริปต์ของคุณ


0

หนึ่งซับ (ไม่มีความแตกต่างที่สำคัญกับคำตอบข้างต้นแม้ว่า)

document.body.appendChild(document.createElement('script')).src = 'source.js';
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.