讲评
节点创建
- 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、换行)
-
推荐做法,用外层盒子包裹