原生JS中的DOM

概述

DOM(文档对象模型)作为HTML、XML、SVG等标记语言的一种编程接口,提供了一种树状的表示方法(DOM树),并提供一系列的事件方法来改变文档内的内容、样式和为这些节点添加一些交互内容。
一般如我们所见,用来操作DOM的是JavaScript,但是DOM并不是JavaScript的一部分,也可以通过其它语言来操作DOM。

一. 节点的增删改查

要对一个元素节点进行操作,最起码要能得到这个节点,才能进行一系列的操作,对一个节点最基础的操作,当然是来自对节点的增删改查:

节点的查询
1
2
3
document.getElementById() // 通过id来查询节点
document.getElementsByClassName() // 通过类名来查询节点
document.getElementsByTagName() // 通过标签名来查询节点

当然,除了从document上去获取节点,也可以从父节点上去获取子节点。
通过以上的方式能够很方便的获取到DOM元素中的所有节点,但方法较多,ES5中提供了一些新的东西来完成阶段的查询:

1
2
Element.querySelector();
Element.querySelectorAll();

在以上两种方式中,以#id.classnode的方式来查询节点,第一种查询到第一个符合条件的的节点,一般用来查询id或者一些只需要第一个节点的场景,第二个则是查询到所有符合条件的节点,并且以对象的形式返回所有的内容。

节点的增加

createElement(node) // 创建一个节点标签
createTextNode() // 创建一个文本节点
node.setAttribute() // 为节点添加属性
通过以上方式创建完成节点并设置好对应属性后,再将创建好的节点添加到html的DOM树中:

1
2
parent.appendChild(child) // 将子元素添加到父元素的的末尾
parent.insertBefore(new,before) // 将元素插入到父元素下原来的元素之前

其余插入方式可以通过其它方法的组合来实现。

节点的删除

parent.removeChild(child) 删除子节点
ChildNode.remove()将自己从所在的DOM树中删除

节点的修改

parent.replaceChild(new,old) // 在父元素下使用新的节点来代替旧的节点。
Node.cloneNode(true) // 克隆一个元素,传入参数可以使falsetruefalse表示只克隆本身,true则表示要克隆本身和所有子节点

二. DOM事件

DOM0/DOM1级

一般来讲,DOM0和DOM1都是对事件所对应函数的定义,一般将它们的区别定义为是否为内联样式:

内联写法

1
2
3
<button onclick=function(){
console.log("hello world.");
}>btn<button>

非内联写法:

1
2
3
4
var btn = document.querySelector("btn");
btn.onclick = function(){
console.log("hello wrold.");
}

这种对事件绑定函数的操作看似简单,但是有一点,一个节点的一个事件函数只能写一次,因为它本身是函数,若是对它进行多次绑定,后面的函数就会覆盖前面的函数,所以在使用这种方式时应该考虑到应用场景。
另外,内联的写法让JavaScript代码与HTML耦合,一般来讲,不推荐这种方式,同样,也不推荐使用内联样式(题外话),并且DOM并未被W3C收入标准中。

DOM2

在DOM0/1中,是对事件所对应的函数进行操作,但是实际上,更多的情况下还应该需要对一个节点的同一个事件进行多次绑定,比如,document上的滚动事件一般就会面临许多次的调用,这时就不能直接对事件对应函数进行重写操作,而是应该对其事件本身进行操作,这时就用到了addEventListener这个监听事件的方法:

1
2
3
4
5
6
7
var btn = document.querySelector("#btn");
btn.addEventListener("click",function(){
console.log("hello");
})
btn.addEventListener("click",function(){
console.log("world");
})

使用DOM2的方式就可以实现同时在一个事件身上绑定两个函数。
addEventListener()中,其实还有一个参数,来说明是否在捕获(Capture)阶段执行处理函数,其默认值为false,代表使用冒泡(Bubbling)方式。
冒泡代表从事件绑定的DOM元素本身向上冒泡,直到document;而捕获方式的查找顺序正好相反。
addEventListener相反,removeEventListener是用来解绑元素的事件的。
在低版本IE下,不支持以上两种方法,则使用attachEventdetachEvent来完成事件的绑定和解绑,与前者不同的是,它的事件处理函数会在全局作用域,也就是window下进行。
此外,addEventListener在需要用到事件代理的场景下也能凸显出它的优势:

1
2
3
4
5
6
var ul = document.quertSelector("ul");
ul.addEventListener("click",function(){
if(e.target.tagName.toLowerCase() === 'li'){
console.log(e.target.innerText);
}
})

DOM3

DOM3在DOM2的基础上增加了很多新的事件,并将事件给进行了分类,比如鼠标事件,键盘事件,滚轮事件,触摸事件等,并增加一些自定义事件,其使用方式和DOM2相同。