DOM
即Document Object Modal。
?
DOM操作中的property和attribute
property:修改對(duì)象屬性,不會(huì)體現(xiàn)在html結(jié)構(gòu)中,例如修改dom的css樣式。
arrtibute:修改html屬性,會(huì)改變html結(jié)構(gòu),比如我給我的p標(biāo)簽加上一個(gè)叫data-name的屬性,屬性的值為p1。
<p data-name='p1'>
二者都有可能引起DOM重新渲染,如果你是要必須修改DOM的結(jié)構(gòu)的話(huà),那就得用arrtibute,平常在使用中盡量使用property,property可能在一些js的機(jī)制中,去重復(fù)避免一些dom的渲染,但arribute一定會(huì)引發(fā)DOM渲染。
?
DOM操作
以下方法沒(méi)有相關(guān)代碼,請(qǐng)讀者自行腦補(bǔ)....
常用獲取節(jié)點(diǎn):
根據(jù)id: document.getElementById('div1')
根據(jù)class:document.getElementsByClassName('div1')
還有一些獲取節(jié)點(diǎn)的方法就不一一列舉了...
①新建節(jié)點(diǎn):document.createElement('p')
②插入節(jié)點(diǎn):div1.appendChild(newP)
③移動(dòng)節(jié)點(diǎn):div1.appendChild(newP),前提是要有這個(gè)newP節(jié)點(diǎn),也就是對(duì)于現(xiàn)有的節(jié)點(diǎn)進(jìn)行appendChild的話(huà),他會(huì)移動(dòng)節(jié)點(diǎn),之前的newP的節(jié)點(diǎn)的位置消失,而不是直接插入
④獲取父元素:p1.parentNode
⑤獲取子元素列表:div1.childNodes,但這個(gè)獲取的所有子元素(包括文本元素,比如你一個(gè)div中有三個(gè)p,每個(gè)p中還各自有一段話(huà),那么childNodes會(huì)把三個(gè)p加三個(gè)text一起算上)
那如果我就想獲取里面的全部p標(biāo)簽,怎么弄呢?
const div1ChildNodesP = Array,prototype.slice.call(div1.childNodes).filter(child => {
if(child.nodeType === 1) {
return true;
}
return false;
});
console.log(div1ChildNodesP);
// filter方法會(huì)創(chuàng)建一個(gè)新數(shù)組,原數(shù)組的每個(gè)元素傳入回調(diào),判斷回調(diào)的return返回值,為true保存到新數(shù)組中,為false則不保存,原數(shù)組不變
⑥刪除節(jié)點(diǎn):div1.removeChild(div1.childNodes[0])
?
DOM性能優(yōu)化(重要)
DOM操作非常昂貴,避免頻繁的DOM操作
①對(duì)DOM查詢(xún)做緩存
// 不緩存 DOM 查詢(xún)結(jié)果
for(let = 0; i < document.getElementsByTagName('p').length; i++) {
// 每次循環(huán),都會(huì)計(jì)算 length,頻繁進(jìn)行 DOM 查詢(xún)
}
// 緩存 DOM 查詢(xún)結(jié)果
const pList = document.getElementsByTagName('p');
const lenght = pList.length;
for(let i = 0; i < length; i++ ) {
// 緩存 length,只進(jìn)行一次 DOM 查詢(xún)
}
②將頻繁操作改為一次操作
普通循環(huán)操作:
const list = document.geElementById('list');
for(let i = 0; i < 10; i++) {
const li = document.createElement('li');
li.innerHTML = `List item ${i}`;
list.appendChild(li);
}
這樣寫(xiě)有沒(méi)有問(wèn)題?沒(méi)有,寫(xiě)的非常好,每次循環(huán),創(chuàng)建一個(gè)li標(biāo)簽,我們就插入到list中,邏輯上沒(méi)有問(wèn)題。但是每次循環(huán)都要插一遍,就很費(fèi)資源了。所以我們的宗旨是要把這些li都一起創(chuàng)建好,最終一起插入。
const list = document.geElementById('list');
// 創(chuàng)建一個(gè)文檔片段,此時(shí)還有插入到 DOM 樹(shù)中
const frag = document.createDocumentFragment();
for(let i = 0; i < 10; i++) {
const li = document.createElement('li');
li.innerHTML = `List item ${i}`;
frag.appendChild(li);
}
// 都完成之后,再插入到 DOM 樹(shù)中
listNode.appendChild(frag);