ความคิดใดที่ว่าทำไมโค้ดส่วนล่างไม่เพิ่มองค์ประกอบสคริปต์ลงใน DOM
var code = "<script></script>";
$("#someElement").append(code);
ความคิดใดที่ว่าทำไมโค้ดส่วนล่างไม่เพิ่มองค์ประกอบสคริปต์ลงใน DOM
var code = "<script></script>";
$("#someElement").append(code);
คำตอบ:
ฉันเคยเห็นปัญหาที่บางเบราว์เซอร์ไม่เคารพการเปลี่ยนแปลงบางอย่างเมื่อคุณทำโดยตรง (ซึ่งฉันหมายถึงการสร้าง HTML จากข้อความเช่นคุณกำลังพยายามแท็กสคริปต์) แต่เมื่อคุณทำด้วยคำสั่งในตัว สิ่งต่าง ๆ ดีขึ้น ลองสิ่งนี้:
var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );
จาก: JSON สำหรับ jQuery
$("#someElement")[0].appendChild( script );
ข่าวดีคือ:
มันใช้งานได้ 100%
alert('voila!');
เพียงแค่เพิ่มสิ่งที่อยู่ภายในแท็กสคริปต์เช่น คำถามที่ถูกที่คุณอาจต้องการถามบางที"ทำไมฉันไม่เห็นมันใน DOM".
คาร์ล Swedberg ได้ทำคำอธิบายที่ดีที่จะแสดงความคิดเห็นของผู้เข้าชมในเว็บไซต์ jQuery API ฉันไม่ต้องการที่จะทำซ้ำทุกคำพูดของเขาที่คุณสามารถอ่านได้โดยตรงมีที่นี่(ผมพบว่ามันยากที่จะนำทางผ่านความเห็นที่นั่น)
วิธีการแทรกของ jQuery ทั้งหมดใช้ฟังก์ชัน domManip ภายในเพื่อล้าง / ประมวลผลองค์ประกอบก่อนและหลังถูกแทรกลงใน DOM หนึ่งในสิ่งที่ฟังก์ชั่น domManip ทำคือการดึงองค์ประกอบสคริปต์ใด ๆ ที่จะถูกแทรกและเรียกใช้ผ่าน "รูทีน evalScript" แทนที่จะฉีดพวกมันด้วยส่วนที่เหลือของ DOM โดยจะแทรกสคริปต์แยกกันประเมินผลจากนั้นลบสคริปต์ออกจาก DOM
ฉันเชื่อว่าหนึ่งในเหตุผลที่ jQuery ทำเพื่อหลีกเลี่ยงข้อผิดพลาด "สิทธิ์ที่อนุญาต" ที่อาจเกิดขึ้นใน Internet Explorer เมื่อแทรกสคริปต์ในบางกรณี นอกจากนี้ยังหลีกเลี่ยงการแทรก / ประเมินสคริปต์เดียวกันซ้ำ ๆ (ซึ่งอาจทำให้เกิดปัญหา) หากอยู่ในองค์ประกอบที่มีที่คุณกำลังแทรกแล้วย้ายไปรอบ ๆ DOM
สิ่งต่อไปคือฉันจะสรุปสิ่งที่เป็นข่าวร้ายโดยใช้.append()
ฟังก์ชั่นเพื่อเพิ่มสคริปต์
และข่าวร้ายก็คือ ..
คุณไม่สามารถดีบักรหัสของคุณได้
ฉันไม่ได้ล้อเล่นแม้ว่าคุณจะเพิ่มdebugger;
คำหลักระหว่างบรรทัดที่คุณต้องการตั้งเป็นเบรกพอยต์คุณจะได้รับการโทรสแต็คของวัตถุเท่านั้นโดยไม่เห็นจุดพักบนซอร์สโค้ด(ไม่ต้องพูดถึงว่านี่ คำหลักใช้งานได้ในเบราว์เซอร์ webkit เท่านั้นเบราว์เซอร์หลักอื่น ๆ ทั้งหมดดูเหมือนจะไม่ใช้คำหลักนี้)ที่สำคัญทุกอย่างดูเหมือนจะละเว้นคำหลักนี้)
หากคุณเข้าใจอย่างถ่องแท้ว่าโค้ดของคุณทำอะไรไปกว่านี้จะเป็นอุปสรรคเล็กน้อย แต่ถ้าคุณทำไม่ได้คุณจะต้องเพิ่มdebugger;
คำหลักให้ทั่วเพื่อหาว่ามีอะไรผิดปกติกับรหัส (หรือของฉัน) ของคุณ อย่างไรก็ตามมีทางเลือกอื่นอย่าลืมว่าจาวาสคริปต์สามารถจัดการ HTML DOM ได้
วิธีแก้ปัญหา
ใช้ javascript (ไม่ใช่ jQuery) เพื่อจัดการ HTML DOM
หากคุณไม่ต้องการสูญเสียความสามารถในการดีบักคุณสามารถใช้ javascript เนทีฟ HTML DOM เนทิฟ ลองพิจารณาตัวอย่างนี้:
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);
มันเป็นเช่นเดียวกับวันเก่าไม่ได้ และอย่าลืมล้างสิ่งต่าง ๆ ไม่ว่าใน DOM หรือในหน่วยความจำสำหรับวัตถุทั้งหมดที่ถูกอ้างถึงและไม่ต้องการอีกต่อไปเพื่อป้องกันการรั่วไหลของหน่วยความจำ คุณสามารถพิจารณารหัสนี้เพื่อทำความสะอาด:
document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.
ข้อเสียของวิธีแก้ปัญหานี้คือคุณอาจเพิ่มสคริปต์ที่ซ้ำกันโดยไม่ตั้งใจและนั่นก็ไม่ดี จากที่นี่คุณสามารถเลียนแบบ.append()
ฟังก์ชันได้เล็กน้อยโดยเพิ่มการตรวจสอบวัตถุก่อนเพิ่มและลบสคริปต์ออกจาก DOM ทันทีหลังจากที่เพิ่ม ลองพิจารณาตัวอย่างนี้:
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;
}
วิธีนี้คุณสามารถเพิ่มสคริปต์ด้วยความสามารถในการดีบักในขณะที่ปลอดภัยจากการทำสำเนาสคริปต์ นี่เป็นเพียงต้นแบบคุณสามารถขยายสิ่งที่คุณต้องการให้เป็น ฉันใช้วิธีนี้และค่อนข้างพอใจกับสิ่งนี้ แน่นอนว่าฉันจะไม่ใช้ jQuery .append()
เพื่อเพิ่มสคริปต์
$.getScript
สร้างขึ้นใน jQuery
เป็นไปได้ที่จะโหลดไฟล์ JavaScript แบบไดนามิกโดยใช้ฟังก์ชั่น jQuerygetScript
$ .getScript ('http://www.whething.com/shareprice/shareprice.js', function () { Display.sharePrice (); });
ตอนนี้สคริปต์ภายนอกจะถูกเรียกใช้และหากไม่สามารถโหลดได้สคริปต์จะลดระดับลงอย่างงดงาม
eval()
ว่า
คุณหมายถึง "ไม่ทำงาน"?
jQuery ตรวจพบว่าคุณกำลังพยายามสร้างองค์ประกอบ SCRIPT และจะเรียกใช้เนื้อหาขององค์ประกอบภายในบริบทส่วนกลางโดยอัตโนมัติ คุณกำลังบอกฉันว่าสิ่งนี้ไม่ได้ผลสำหรับคุณ -
$('#someElement').append('<script>alert("WORKING");</script>');
แก้ไข: หากคุณไม่เห็นองค์ประกอบ SCRIPT ใน DOM (ใน Firebug เป็นต้น) หลังจากที่คุณเรียกใช้คำสั่งที่เป็นเพราะ jQuery อย่างที่ฉันพูดจะเรียกใช้รหัสแล้วจะลบองค์ประกอบ SCRIPT - ฉันเชื่อว่าองค์ประกอบ SCRIPT ถูกผนวกเข้ากับเนื้อความเสมอ ... แต่อย่างไรก็ตาม - การจัดวางไม่มีผลต่อการเรียกใช้โค้ดในสถานการณ์นี้อย่างแน่นอน
งานนี้:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
ดูเหมือนว่า jQuery กำลังทำสิ่งที่ฉลาดกับสคริปต์ดังนั้นคุณต้องผนวกองค์ประกอบ html แทนวัตถุ jQuery
ลองสิ่งนี้อาจเป็นประโยชน์:
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);
ฉันต้องการทำสิ่งเดียวกัน แต่เพื่อผนวกแท็กสคริปต์ในเฟรมอื่น!
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);
<script>
...
...jQuery("<script></script>")...
...
</script>
</script>
ภายในสตริงสิ้นสุดที่แท้จริงทั้งสคริปต์เพื่อหลีกเลี่ยงการที่"</scr" + "ipt>"
สามารถนำมาใช้แทน
"\x3cscript\x3e\x3c/script\x3e"
ลำดับหนี: ใน XHTML คุณจะต้องใส่บล็อก CDATA ที่ถูกใส่ความคิดเห็นเท่านั้น
</
ที่ไม่ได้รับอนุญาต ดูstackoverflow.com/questions/236073/…
การเพิ่ม sourceURL ในไฟล์สคริปต์ช่วยตามที่กล่าวไว้ในหน้านี้: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
สคริปต์ของคุณกำลังทำงานคุณไม่สามารถใช้งานdocument.write
ได้ document.write
ใช้การแจ้งเตือนเพื่อทดสอบและหลีกเลี่ยงการใช้ คำสั่งของไฟล์ js ของคุณด้วยdocument.write
จะไม่ถูกดำเนินการและส่วนที่เหลือของฟังก์ชั่นจะถูกดำเนินการ
นี่คือสิ่งที่ฉันคิดว่าเป็นทางออกที่ดีที่สุด Google Analytics ถูกฉีดด้วยวิธีนี้
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); })();
คุณไม่จำเป็นต้อง jQuery เพื่อสร้างสคริปต์องค์ประกอบ DOM มันสามารถทำได้กับวานิลลา ES6 เช่น:
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!'))
ไม่จำเป็นต้องห่อในPromise
แต่การทำเช่นนั้นจะช่วยให้คุณสามารถแก้ไขสัญญาเมื่อสคริปต์โหลดขึ้นช่วยป้องกันสภาวะการแข่งขันสำหรับสคริปต์ที่รันนาน
ผนวกสคริปต์เข้ากับเนื้อหา:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
วิธีการที่คุณสามารถทำมันได้ถ้าคุณต้องการรหัสต่อท้ายก็คือการใช้document.createElement
วิธีการ แต่แล้วใช้แทน.innerHTML
.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 );
ฉันพยายามนี้อย่างใดอย่างหนึ่งและผลงานที่ดี เพียงแค่แทนที่<
สัญลักษณ์ด้วยสิ่ง\x3C
นั้น
// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);
หรือ
//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");
ลองแบบนี้
var code = "<script></" + "script>";
$("#someElement").append(code);
เหตุผลเดียวที่คุณไม่สามารถทำได้"<script></script>"
คือไม่อนุญาตให้ใช้สตริงใน javascript เพราะเลเยอร์ DOM ไม่สามารถแยกว่า js คืออะไรและ HTML คืออะไร
ฉันเขียนnpm
แพคเกจที่ช่วยให้คุณใช้สตริง HTML รวมถึงแท็กสคริปต์และผนวกเข้ากับคอนเทนเนอร์ในขณะดำเนินการสคริปต์
ตัวอย่าง:
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)
ค้นหาได้ที่นี่: https://www.npmjs.com/package/appendhtml
เพียงสร้างองค์ประกอบโดยแยกวิเคราะห์ด้วย jQuery
<div id="someElement"></div>
<script>
var code = "<script>alert(123);<\/script>";
$("#someElement").append($(code));
</script>
ตัวอย่างการทำงาน: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz