3 回答

TA貢獻1824條經驗 獲得超8個贊
這種將HTML元素從一個地方“復制”到另一個地方的方法是對瀏覽器功能的錯誤理解的結果。瀏覽器不會將HTML文檔保存在內存中的某個位置,而是會根據來自JavaScript的命令反復修改HTML。
當瀏覽器首次加載頁面時,它將解析 HTML文檔并將其轉換為DOM結構。這是遵循W3C標準的對象之間的關系(嗯,主要是...)。從那時起,原始的HTML是完全多余的。瀏覽器不在乎原始的HTML結構是什么。它對網頁的理解是從中創建的DOM結構。如果您的HTML標記不正確/無效,則網絡瀏覽器會通過某種方式對其進行更正;DOM結構不會以任何方式包含無效代碼。
基本上,HTML應該被視為對DOM結構進行序列化的一種方式,以使其可以通過Internet傳遞或存儲在本地文件中。
因此,不應將其用于修改現有網頁。DOM(文檔對象模型)具有用于更改頁面內容的系統。這是基于節點的關系,而不是基于HTML序列化。因此,當你添加一個li到ul,你有這兩個選項(假設ul是列表元素):
// option 1: innerHTML
ul.innerHTML += '<li>foobar</li>';
// option 2: DOM manipulation
var li = document.createElement('li');
li.appendChild(document.createTextNode('foobar'));
ul.appendChild(li);
現在,第一個選項看起來簡單很多,但這只是因為瀏覽器為您提供了很多抽象的東西:在內部,瀏覽器必須將元素的子代轉換為字符串,然后附加一些內容,然后將字符串轉換回DOM結構。第二個選項對應于瀏覽器對正在發生的事情的本機理解。
第二個主要考慮因素是考慮HTML的局限性??紤]網頁時,并非與元素相關的所有內容都可以序列化為HTML。例如,與綁定的事件處理程序x.onclick = function();或x.addEventListener(...)不會在中復制的事件處理程序innerHTML,因此不會在它們之間進行復制。因此,其中的新元素y將沒有事件偵聽器。這可能不是您想要的。
因此,解決此問題的方法是使用本機DOM方法:
for (var i = 0; i < x.childNodes.length; i++) {
y.appendChild(x.childNodes[i].cloneNode(true));
}
閱讀MDN文檔可能會有助于理解這種處理方式:
appendChild
cloneNode
childNodes
現在,此問題(如上面的代碼示例中的選項2一樣)的問題是,它非常冗長,比該innerHTML選項要長得多。當您欣賞擁有一個為您執行此類操作的JavaScript庫時。例如,在jQuery中:
$('#y').html($('#x').clone(true, true).contents());
這對您想要發生的事情更為明確。例如,除了具有各種性能優勢和保留事件處理程序外,它還可以幫助您了解代碼在做什么。這對于您作為JavaScript程序員的靈魂來說是一件好事,并且使異常錯誤的可能性大大降低!
添加回答
舉報