DOM编程

103 阅读4分钟

网页其实是一棵树

4.png

JS如何操作这棵树

  • 浏览器往window上加一个document即可

JS用document操作网页(DOM树)

  • 这就是Document Object Model 文档对象模型

获取元素(Element),也叫标签(tag)

有很多API

  • window.idxxx或者直接idxxx (名字不跟全局属性冲突是可以用这个)

  • document.getElementById('Idxxx') (与全局属性冲突时用这个)

  • document.getElementsByTagName('div')[0] (找到一个标签名为div的元素,前面是一个伪数组,[]里面是代表div元素里面的第几个)

  • document.getElementsByClassName('red')[0] (根据类名来获取class=red的标签)

  • document.querySelector('#idxxx') (例如:document.querySelector('div>span:nth-child(2)'))

  • document.querySelectorAll('.red')[0] (获取符合条件的所有标签)

练练手

  • 假设页面中有如下元素
<div id="test" class="red">demo</div>

以下获取该 div 元素的代码中,正确的有

  • document.getElementById('test')

  • document.getElementsByClassName('red')[0]

  • window.test

  • document.querySelector('#test')

  • document.querySelectorAll('#test')[0]

获取特定元素

获取html元素

  • document.documentElement(document.documentElement.tagName打印出来的是大写的HTML)

获取head元素

  • document.head

获取body元素

  • document.body

获取窗口(窗口不是元素)

  • window

获取所有元素

  • document.all(是IE发明的,用来分辨是不是IE,它过不了if,但是可以直接用)

  • 这个document.all 是个奇葩,第六个falsy值

获取到的元素是个啥(显然是一个对象)

5.png

div完整原型链(自身属性和共有属性)

8.png

节点?、元素?

节点Node包括以下几种

  • MDN有详细的描述,x.nodeType得到一个数字,表示常量

  • 1表示元素Element,也叫标签Tag

  • 3表示文本Text

  • 8表示注释Comment

  • 9表示文档Document

  • 11表示文档片段DocumentFragment

  • 记住1和2即可

7.png

增删改查

创建一个标签节点

  • let div1 = document.createElement('div')

  • document.createElement('style')

  • document.createElement('script')

  • document.createElement('li')

创建一个文本节点

  • text1 = document.createTextNode('你好')

标签里面插入文本

  • div1.appendChild(text1)

  • div1.innerText = '你好' 或者 div1.textContent = '你好'

  • 但是不能用div1.appendChild('你好')(注意:text是对象,'你好'是字符串)

插入页面中

  • 你创建的标签默认处于JS线程中

  • 你必须把它插到head或者body里面,它才会生效

  • document.bady.appendChild(div)

  • 或者,已在页面中的元素 .appendChild(div)

appendChild

9.png

  • 答案:text2里面,一个元素不能出现在两个地方,除非复制一份

2.png

两种方法

旧方法:parentNode.remoteChild(childNode)

新方法:childNode.remove()

  • 移回页面:document.head/body.appendChild(div)

改属性

读标准属性

10.png

改事件处理函数

11.png

12.png

  • 注意:x是event, test是this

改内容

改文本内容

  • div.innerText = 'xxx'

  • div.innerContent = 'xxx'

  • 两者几乎没有区别

改HTML内容

  • div.innerHTML = '重要内容'

改标签

  • div.innerHTMl = ''//先清空

  • div.appendChild(div2) //在加内容

改父级(改爸爸)

  • newParent.appendChild(div)

  • 直接这样就可以了,直接从原来的地方消失

查父级(查爸爸)

  • node.parentNode或者node.parentElement

查父级的父级(查爷爷)

  • node.parentNode.parentNode

查子级(查子代)

  • node.childNodes或者node.children

  • 注意:childNodes是Node提供的,children 是Element提供的,第一种会把回车空格算下来,包括文本节点,第二个不包括文本节点。当用document.querySelectorAll('')获取元素时则子代变化时,不会随时改变属性。

查兄弟姐妹

  • node.parentNode.childNode还要排除自己

  • node.parentNode.children还要排除自己

let sibling = []
let c = div2.parentElement.children
for(let i=0;i<c.length;i++){
   if(c[i] !== div2){
    sibling.push(c.[i])
  }
}

查看老大

  • node.firstChild

查看老幺

  • node.lastChild

查看上一个哥哥/姐姐

  • node.previousSibling

查看下一个弟弟/妹妹

  • mode.nextSibling

遍历一个div里面的所有元素

image.png

DOM操作是跨线程的

  • 浏览器功能划分渲染引擎和JS引擎

跨线程操作

各线程各司其职

  • JS引擎不能操作页面,只能操作JS

  • 渲染引擎不能操作JS,只能操作页面

  • document.body.appendChild(div1)

跨线程通信

  • 当浏览器发现JS在body里面加了个div1对象

  • 浏览器就会通知渲染引擎在页面里也新增一个div元素

  • 新增的div元素所有的属性都照抄div1对象

跨线程操作图

image.png

插入新标签的完整过程

在div放入页面之前

  • 你对div所有的操作都属于JS线程内的操作

把div放入页面之时

  • 浏览器会发现JS对应的意图,就会通知渲染进程在页面中渲染div1对应的元素

把div1放入页面之后

  • 你对div1的操作都有可能会触发重新渲染

  • div1.id ='newId' 可能会重新渲染,也可能不会

  • div1.title ='new' 可能会重新渲染,也可能不会

  • 如果你连续对div1多次操作,浏览器可能会合并成一个操作,也可能不会

添加.png

属性同步

标准同步

  • 对非标准属性的修改,则只会停留在JS线程里

  • 比如id、className、title等

data-* 属性

  • 同上

非标准属性

  • 对应标准属性的修改,则只会停留在JS线程中,不会同步到页面

启示

  • 如果有自定义属性,不想同步到页面中,请使用data-* 属性

15.png

property V.S Attribute

property属性

  • JS线程中div1的所有属性,叫做div1的property

attribute也是属性

  • 渲染引擎div1 对应的标签的属性,叫做attribute

区别

  • 大部分时候,同名的property和attribute值相等

  • 但如果不是标准的属性,那么他两只会一开始相等

  • property支持字符串、布尔等类型

  • attribute只支持字符串