講評
節點創建
- Document.prototype ←
document.createElement('div')
document.createTextNode('xxx')
// 創建文本節點document.createComment('xxx')
// 創建注釋節點
增加/剪切子節點
- Node.prototype ←
node.appendChild(node)
- 總是在父元素的最后增加(類似push)
- 同時也能剪切(對于存在的節點/DOM元素),可用于移動位置,絕不能寫字符串
插入insertBefore
- Node.prototype
c.insertBefore(a, b)
在父級c節點下的子節點b前插入a節點,新的在前- 最后插的總是緊靠著舊的節點
<body><div><p class="firstP">666</p></div><script>var div = document.getElementsByTagName('div')[0]var fP = document.getElementsByClassName('firstP')[0]var oP = document.createElement('p')oP.innerHTML = '222'div.insertBefore(oP, fP)var sP = document.createElement('p')sP.innerHTML = '333'div.insertBefore(sP, fP)</script>
</body>
刪除節點 removeChild
- Node.prototype
父節點.removeChild(子節點)
// 返回被刪除的節點- 元素是由構造函數實例化創建的,dom對象存到了內存中,刪除節點并沒有釋放內存
刪除釋放節點remove
節點自身.remove()
- 返回undefined
- 內存也釋放了
節點替換
父節點.replaceChild(新, 舊)
innerHTML innerText
原型 | 屬性 |
---|---|
Element.prototype | innerHTML |
HTMLElement.prototype | innerHTML innerText |
- innerHTML可讀寫
- += 追加賦值
- 可寫文本 or HTML字符串
- innerText會過濾標簽
- innerText賦值為標簽,也會將標簽轉換為字符實體,依然是字符
- innerText在老版本的火狐對應textConent,但老版本的IE不支持textContent
元素節點方法
div.setAttribute('id','box')
div.getAttribute('class')
自定義屬性
- HTML5中增加
data-*
屬性 - 自定義的屬性通過
節點.dataset
來管理 - dataset在移動端兼容,PC端IE9及以下不兼容(無此屬性)
創建文檔碎片
document.createDocumentFragment()
- 給瀏覽器渲染引擎減負,減少計算位置/回流
- 當oDiv還沒有在節點樹里的時候append,但結果多了一個div節點
- 而文檔碎片是節點,但不在dom樹上,存在內存中,nodeType12,不會引起頁面的回流
- 字符串的性能更好
練習
- 原型上編程 hasChildren 判斷父元素有沒有子元素節點
Element.prototype.hasChildren = function () {var arr = this.childNodesif (arr.length === 0) {return false} else {for (var i = 0; i < arr.length; i++) {if (arr[i].nodeType === 1) {return true}}return false}
}
var div = document.getElementsByTagName('div')[0]
var h1 = document.getElementsByTagName('h1')[0]
console.log(div.hasChildren())
console.log(h1.hasChildren())
- 原型上編程 尋找兄弟元素節點 參數為正找之后第n個,參數為負找之前第n個,參數0返回自己
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div><h1></h1><p></p><a href=""></a><span></span></div><script>Element.prototype.findSibling = function () {var index = arguments[0] || 0if (!index) {return this} else {var times = Math.abs(index)var node = thisfor (var i = 0; i < times; i++) {node = findFn(node, index)}return node}}function findFn(node, index) {if (index > 0) {return node.nextElementSibling} else {return node.previousElementSibling}}var h1 = document.getElementsByTagName('h1')[0]var found = h1.findSibling(3)var a = document.getElementsByTagName('a')[0]var found2 = a.findSibling(-2)console.log(found)console.log(found2)</script>
</body></html>
- 用js創建文檔碎片
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="box"></div><script>var div = document.getElementsByTagName('div')[0],oUl = document.createElement('ul');oUl.className = 'list'var oDivFragment = document.createDocumentFragment('div')for (var i = 0; i < 5; i++) {var oLi = document.createElement('li')oLi.className = 'list-item'oLi.innerText = i + 1oDivFragment.appendChild(oLi)}oUl.appendChild(oDivFragment)div.appendChild(oUl)</script>
</body></html>
- 遍歷一個父級元素下面所有的子元素節點
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div class="grandfather"><p></p><div><h1></h1><span></span><div><a href=""></a><h2></h2></div></div></div><script>Element.prototype.getAllChildren = function () {var arr = this.childNodesvar eleArr = []getChildren(arr, eleArr)return eleArr}function getChildren(arr, eleArr) {for (var i = 0; i < arr.length; i++) {if (arr[i].nodeType === 1) {eleArr.push(arr[i])if (arr[i].hasChildNodes()) {getChildren(arr[i].childNodes, eleArr)}}}}var oGF = document.getElementsByClassName('grandfather')[0]var children = oGF.getAllChildren()console.log(children)</script>
</body></html>
-
原型上封裝insertAfter 用insertBefore實現
-
子元素逆序
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div class="grandfather"><h1>1</h1><span>2</span><div>3</div><p>4</p></div><script>Element.prototype.myReverse = function () {var arr = this.childNodes,children = []for (var i = 0; i < arr.length; i++) {var ele = arr[i]if (ele.nodeType === 1) {children.push(ele)}}for (var j = children.length - 1; j >= 0; j--) {var e = children[j]this.appendChild(e)}}var oGF = document.getElementsByClassName('grandfather')[0]</script>
</body></html>
18-1 innerHTML
- Element.prototype上的屬性
- 對于特殊符號,獲取到的是字符實體
- document.body.innerHTML / document.documentElement.innerHTML(不能直接在document上用此屬性)
- 會刪除元素內原有的內容
- outerHTML - 替換掉包含父元素的所有內容
- 獲取dom元素字符串,并用pre(將字符實體轉成符號)
- 設置innerHTML時:
- 將字符串解析為HTML文檔
- 用documentFragment將這個文檔結構變成DOM節點
- 原本父節點上的所有內容都會被替換成這個節點
- 性能問題,慢
- 安全問題:HTML5和現代的新的瀏覽器會組織通過innerHTML嵌入腳本的程序執行
- 插入純文本時,使用Node.textContent更好,只會將文本插入到元素內部去,不會解析為HTML文檔
- 追innerHTML會破壞原先的DOM應用
innerText
-
純文本設置時,和textContent效果相同(盡量使用textContent)
-
innerText會忽略非標簽內容(比如style、換行)
-
推薦做法,用外層盒子包裹