การแทรกองค์ประกอบ HTML ด้วย JavaScript


105

แทนที่จะค้นหาวิธีแก้ปัญหาที่น่าเบื่อหน่ายสำหรับแอตทริบิวต์และเหตุการณ์แต่ละประเภทเมื่อใช้ไวยากรณ์ต่อไปนี้:

elem = document.createElement("div");
elem.id = 'myID';
elem.innerHTML = ' my Text '
document.body.insertBefore(elem,document.body.childNodes[0]);

มีวิธีที่ฉันสามารถประกาศองค์ประกอบ HTML ทั้งหมดเป็นสตริงได้หรือไม่? ชอบ:

elem = document.createElement("<div id='myID'> my Text </div>");
document.body.insertBefore(elem,document.body.childNodes[0]);

คำตอบ:


124

แทนที่จะไปยุ่งกับinnerHTMLมันโดยตรงอาจเป็นการดีกว่าที่จะสร้างชิ้นส่วนแล้วแทรกสิ่งนั้น:

function create(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

var fragment = create('<div>Hello!</div><p>...</p>');
// You can use native DOM methods to insert the fragment:
document.body.insertBefore(fragment, document.body.childNodes[0]);

สิทธิประโยชน์:

  1. คุณสามารถใช้วิธี DOM ดั้งเดิมสำหรับการแทรกเช่น insertBefore, appendChild เป็นต้น
  2. คุณสามารถเข้าถึงโหนด DOM จริงก่อนที่จะแทรก คุณสามารถเข้าถึงอ็อบเจ็กต์ childNodes ของแฟรกเมนต์
  3. การใช้ชิ้นส่วนเอกสารนั้นรวดเร็วมาก เร็วกว่าการสร้างองค์ประกอบภายนอก DOM และในบางสถานการณ์เร็วกว่า innerHTML

แม้ว่าinnerHTMLจะใช้ภายในฟังก์ชัน แต่ทั้งหมดนี้เกิดขึ้นนอก DOM ดังนั้นจึงเร็วกว่าที่คุณคิดไว้มาก ...


3
ฉันพนันได้เลยว่า createDocumentFragment () นี้จะไม่ดีเท่ากับ innerHTML "ดั้งเดิม"
TheFlash

2
วิธีนี้ใช้ได้กับเบราว์เซอร์สมัยใหม่ทั้งหมด สำหรับ IE 5.5 และต่ำกว่าคุณสามารถทำการตรวจสอบเช่น :: if (document.createDocumentFragment) {create ('... '); } else {/ * ใช้ innerHTML บางที * /}
James

32
crescentfresh ฉันช่วย SO เพราะฉันชอบช่วยเหลือผู้คน ขออภัยหากโซลูชันไม่สามารถใช้งานได้ 100% ในทุกสถานการณ์ หากคุณกังวลมากทำไมไม่เสนอวิธีแก้ปัญหาของคุณเองแทนที่จะวิจารณ์คำตอบที่เสนอไปแล้วโดยไม่จำเป็น? ด้วยสิ่งที่เป็นนามธรรมใด ๆ จะมีกรณีขอบเสมอ! นี่คือสภาพแวดล้อมการเรียนรู้ - เราไม่ได้อยู่ที่นี่เพื่อให้คำตอบแก่ผู้คนบนจาน - เรามาที่นี่เพื่อช่วยกันพัฒนาสิ่งที่เราทำให้ดีขึ้น! และขอโทษ แต่ใครเอ่ยถึง "AJAX" มาจากไหน?
เจมส์

1
พอใช้. ขอโทษด้วย. ฉันแค่รู้สึกว่ามีนามธรรมมากมายที่นี่โดยไม่มีข้อแม้ที่กล่าวถึง
Crescent Fresh

1
นี่เป็นวิธีที่ซับซ้อนกว่าที่จำเป็น - คำตอบของ sime vidas นั้นดีกว่ามาก
JonnyRaa

84

คุณต้องการสิ่งนี้

document.body.insertAdjacentHTML( 'afterbegin', '<div id="myID">...</div>' );

13
ไม่แน่ใจว่าเหตุใดจึงไม่ใช่คำตอบที่ยอมรับ นี่เป็นวิธีที่ง่ายกว่าและถูกต้องชัดเจนกว่า
JonnyRaa

@JonnyLeeds สิ่งนี้ดูเหมือนจะไม่ทำงานกับbodyองค์ประกอบ แต่ทำงานได้ดีกับองค์ประกอบอื่น ๆ
Phill

1
@Phill แน่นอนมันใช้งาน<body>ได้ ตามความเป็นจริงการเปิดใช้งาน<body>เป็นวิธีมาตรฐานของฉันในการฉีดสิ่งต่างๆเช่นสไตล์ชีตลงในหน้าเว็บผ่านคอนโซล คุณมีปัญหาอะไร
Šime Vidas

@ ŠimeVidasอาจเป็นเพราะไม่ได้กำหนดองค์ประกอบของร่างกายในเวลาดำเนินการ ... ฉันจับคู่บรรทัดของคุณกับ window.onload = function () {…} เพื่อป้องกันปัญหานั้น
GDY

@Grandy Phill เขียนว่ามันทำงานกับองค์ประกอบอื่น ๆ หาก<body>ไม่ได้กำหนดก็จะเป็นองค์ประกอบอื่น ๆ ทั้งหมดดังนั้นนี่ไม่ใช่ปัญหาของ Phill
Šime Vidas

32

ดูที่insertAdjacentHTML

var element = document.getElementById("one");
var newElement = '<div id="two">two</div>'
element.insertAdjacentHTML( 'afterend', newElement )
// new DOM structure: <div id="one">one</div><div id="two">two</div>

ตำแหน่งคือตำแหน่งที่สัมพันธ์กับองค์ประกอบที่คุณแทรกซึ่งอยู่ติดกับ:

'beforebegin' ก่อนองค์ประกอบนั้นเอง

'afterbegin' อยู่ภายในองค์ประกอบก่อนลูกคนแรก

'beforeend' อยู่ภายในองค์ประกอบหลังจากลูกคนสุดท้าย

'afterend' หลังจากองค์ประกอบนั้นเอง


17

ใน JavaScript ของโรงเรียนเก่าคุณสามารถทำได้:

document.body.innerHTML = '<p id="foo">Some HTML</p>' + document.body.innerHTML;

ตอบกลับความคิดเห็นของคุณ:

[... ] ฉันสนใจที่จะประกาศที่มาของแอตทริบิวต์และเหตุการณ์ขององค์ประกอบใหม่ไม่ใช่innerHTMLขององค์ประกอบ

คุณต้องฉีด HTML ใหม่ลงใน DOM แม้ว่า; นั่นเป็นเหตุผลที่innerHTMLใช้ในตัวอย่าง JavaScript ของโรงเรียนเก่า innerHTMLของBODYองค์ประกอบใช้ได้กับ HTML ใหม่ เราไม่ได้สัมผัส HTML ที่มีอยู่ภายในไฟล์BODY.

ฉันจะเขียนตัวอย่างข้างต้นอีกครั้งเพื่อชี้แจงสิ่งนี้:

var newElement = '<p id="foo">This is some dynamically added HTML. Yay!</p>';
var bodyElement = document.body;
bodyElement.innerHTML = newElement + bodyElement.innerHTML;
// note that += cannot be used here; this would result in 'NaN'

การใช้เฟรมเวิร์ก JavaScript จะทำให้โค้ดนี้มีรายละเอียดน้อยลงและเพิ่มความสามารถในการอ่าน ตัวอย่างเช่น jQuery อนุญาตให้คุณทำสิ่งต่อไปนี้:

$('body').prepend('<p id="foo">Some HTML</p>');

ใช้ได้ดีทีเดียว. แต่ฉันสนใจที่จะประกาศที่มาของแอตทริบิวต์และเหตุการณ์ขององค์ประกอบใหม่ไม่ใช่ innerHTML ขององค์ประกอบ
TheFlash

1
document.getElementsByTagName('body')[0]สามารถถูกแทนที่ได้ด้วยdocument.bodyจุดที่ดี อย่างไรก็ตามหากคุณต้องการต่อท้ายหรือต่อท้าย HTML ใหม่กับองค์ประกอบอื่นที่มีอยู่แทนที่จะเป็น BODY คุณจะต้องใช้document.getElementById()และ / หรือdocument.getElementsByTagName(); นั่นคือเหตุผลที่ฉันใช้ในตัวอย่าง
Mathias Bynens

1
นอกจากนี้รหัสของคุณอาจยุ่งเหยิงได้อย่างรวดเร็วหากคุณเพิ่ม / แทรก "innerHTML" โดยตรง
James

1
@JimmyP: ขยะอะไร! จุดประสงค์ของคำถามนี้คือเพื่อให้สามารถแทรก HTML เป็นสตริงได้โดยตรงแทนที่จะเล่นกับฟังก์ชันเพื่อสร้างแอตทริบิวต์โดยแอตทริบิวต์โหนดต่อโหนดองค์ประกอบตามองค์ประกอบ
TheFlash

1
สิ่งนี้จะปลดตัวจัดการเหตุการณ์ทั้งหมดและอาจทำให้หน่วยความจำรั่วไหลครั้งใหญ่
adardesign

1

สำหรับความรู้ของฉันซึ่งตามความเป็นธรรมนั้นค่อนข้างใหม่และมีข้อ จำกัด ปัญหาเดียวที่อาจเกิดขึ้นกับเทคนิคนี้คือความจริงที่ว่าคุณถูกป้องกันไม่ให้สร้างองค์ประกอบตารางแบบไดนามิก

ฉันใช้แบบฟอร์มเพื่อสร้างเทมเพลตโดยการเพิ่มองค์ประกอบ "เทมเพลต" ลงใน DIV ที่ซ่อนอยู่จากนั้นใช้ cloneNode (true) เพื่อสร้างโคลนและต่อท้ายตามต้องการ โปรดทราบว่าคุณต้องตรวจสอบให้แน่ใจว่าคุณได้กำหนดรหัสใหม่ตามที่กำหนดเพื่อป้องกันการทำซ้ำ


-1

ดังที่คนอื่นกล่าวว่าสามารถจำลองฟังก์ชันjQuery prepend ที่สะดวกได้:

var html = '<div>Hello prepended</div>';
document.body.innerHTML = html + document.body.innerHTML;

ในขณะที่บางคนบอกว่าอย่า "ยุ่ง" กับinnerHTMLแต่ก็น่าเชื่อถือในหลาย ๆ กรณีการใช้งานหากคุณทราบสิ่งนี้:

ถ้า<div>, <span>หรือ<noembed>โหนดมีโหนดข้อความของเด็กที่มีตัวละคร ( &) ( <) หรือ ( >) innerHTML ผลตอบแทนที่ตัวละครเหล่านี้เป็น&amp, &ltและ&gtตามลำดับ ใช้Node.textContentเพื่อรับสำเนาที่ถูกต้องของเนื้อหาของโหนดข้อความเหล่านี้

https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

หรือ:

var html = '<div>Hello prepended</div>';
document.body.insertAdjacentHTML('afterbegin', html)

insertAdjacentHTMLน่าจะเป็นทางเลือกที่ดี: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML


-2

หากคุณต้องการที่จะแทรกโค้ด HTML ภายในเพจที่มีอยู่ของแท็กใช้Jnerator เครื่องมือนี้สร้างขึ้นเป็นพิเศษสำหรับเป้าหมายนี้

แทนที่จะเขียนโค้ดถัดไป

    var htmlCode = '<ul class=\'menu-countries\'><li
        class=\'item\'><img src=\'au.png\'></img><span>Australia </span></li><li
        class=\'item\'><img src=\'br.png\'> </img><span>Brazil</span></li><li
        class=\'item\'> <img src=\'ca.png\'></img><span>Canada</span></li></ul>';
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

คุณสามารถเขียนโครงสร้างที่เข้าใจได้มากขึ้น

    var jtag = $j.ul({
        class: 'menu-countries',
        child: [
            $j.li({ class: 'item', child: [
                $j.img({ src: 'au.png' }),
                $j.span({ child: 'Australia' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'br.png' }),
                $j.span({ child: 'Brazil' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'ca.png' }),
                $j.span({ child: 'Canada' })
            ]})
        ]
    });
    var htmlCode = jtag.html();
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.