1纵穿、節(jié)點(diǎn)類型
常用節(jié)點(diǎn)一共分為三種下隧,分別是元素節(jié)點(diǎn)(element)、屬性節(jié)點(diǎn)(attribute)政恍、文本節(jié)點(diǎn)(text)汪拥。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="test">
</div>
</body>
</html>
<script>
const elementNode = document.getElementById('test')
const attrNode = elementNode.getAttributeNode('id')
const textNode = elementNode.firstChild
console.log(elementNode.nodeType) // 1 元素節(jié)點(diǎn)
console.log(attrNode.nodeType) // 2 元素節(jié)點(diǎn)
console.log(textNode.nodeType) // 3 文本節(jié)點(diǎn)
</script>
2、Object.defineProperty
給對象添加屬性:
Object.defineProperty(obj,prop,{descriptor})
obj:要定義屬性的對象
prop:要定義或修改的屬性名稱
descriptor:屬性的描述信息
屬性描述符:
1)configurable: (屬性)是否可重新定義
2)enumerable: (屬性)是否可枚舉
3)value: (屬性)對應(yīng)的初始值
4)writable: (屬性)是否可被修改
let obj = {
firstName:'A',
lastName:'B'
}
Object.defineProperty(obj,'fullName',{
configurable: true, // 可以重新定義屬性
enumerable:false,// 不能枚舉屬性
value:'G-H',
writable:false // 不能修改屬性
})
//writable
console.log(obj.fullName) //value G-H
obj.fullName = 'J-K'//修改了屬性值
console.log(obj.fullName)//仍舊是G-H篙耗,不可修改
//configurable
Object.defineProperty(obj,'fullName',{
enumerable:false,
value:'M-N',
}) //如果configurable設(shè)置為false迫筑,則會拋異常-->TypeError: Cannot redefine property: fullName
//enumerable
const names = Object.keys(obj)
console.log(names) //[ 'firstName', 'lastName' ]宪赶,fullName屬性無法枚舉出來
訪問描述符:
5)get: 回調(diào)函數(shù),根據(jù)其他相關(guān)的屬性脯燃,動態(tài)計算得到當(dāng)前屬性值
6)set: 回調(diào)函數(shù)搂妻,監(jiān)視當(dāng)前屬性值的變化,更新其他相關(guān)屬性
Object.defineProperty(obj,'fullName',{
get(){
return this.firstName + '-' + this.lastName
},
set(val){
const names = val.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
})
//get
console.log(obj.fullName) // A-B
obj.firstName = 'C'
obj.lastName = 'D'
console.log(obj.fullName) // C-D get動態(tài)獲取值
//set
obj.fullName = 'E-F'
console.log(obj.firstName,obj.lastName) //E F
3辕棚、obj.hasOwnProperty(prop)
判斷對象自身屬性中规惰,是否具有指定的屬性
var obj = {
firstName: 'A'
}
console.log(obj.hasOwnProperty('firstName')) // true
console.log(obj.hasOwnProperty('toString')) // false
4棕所、文檔碎片DocumentFragment
文檔碎片的api可以參考這篇文檔:
https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment
document和fragment的區(qū)別:
document:對應(yīng)顯示的頁面,包含n個element,一旦更新了document內(nèi)部的某個元素劫映,整個界面都要更新房午;
fragment:內(nèi)存中保存n個element的容器蹋绽,不與界面關(guān)聯(lián)拍霜,如果更新fragment中的某個element,界面不變挽铁。
有了文檔碎片伟桅,我們就可以更為高效的批量更新多個節(jié)點(diǎn)了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<ul id="frag">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</div>
</body>
</html>
<script>
//document:對應(yīng)顯示的頁面叽掘,包含n個element楣铁,一旦更新了document內(nèi)部的某個元素,整個界面都要更新
//documentFragment:內(nèi)存中保存n個element的容器更扁,不與界面關(guān)聯(lián)盖腕,如果更新fragment中的某個element,界面不變
const ul = document.getElementById('frag')
console.log(ul.innerHTML)
//1.創(chuàng)建fragment
const fragment = document.createDocumentFragment()
//2.取出ul中所有子節(jié)點(diǎn),(包含換行等文本子節(jié)點(diǎn))
let child = null
while (child = ul.firstChild) { // 一個節(jié)點(diǎn)只有一個父親(節(jié)點(diǎn)或隸屬document疯潭,或隸屬fragment赊堪,二選一)
fragment.appendChild(child) // 先將child從document移除,然后放入fragment
} //每迭代一次竖哩,ul中的節(jié)點(diǎn)出棧
console.log(ul.innerHTML) // 空哭廉,已經(jīng)將節(jié)點(diǎn)全部轉(zhuǎn)移到fragment中了
//3.更新fragment中的所有l(wèi)i的內(nèi)容
let nodes = [].slice.call(fragment.childNodes)
nodes.forEach(node => {
if (node.nodeType === 1) {
node.textContent = 'hello'
}
})
//4.將fragment插回ul
ul.appendChild(fragment)
</script>