前端开发始终绕不过的就是操作DOM,在Vue,Angular,React等框架出现后,我们通过操作数据来控制DOM(绝大多数时候),越来越少的去直接操作DOM。
但是并不是所有时候都一定要引入这些库,对于基础的JS操作DOM的方法,还是需要掌握的。
一、查询
1.按照ID查询
document.getElementById(id) // 兼容最好
这个接口很简单,根据元素id返回元素,返回值是Element类型,如果不存在该元素,则返回null。
语法:
const mainDom = document.getElementById('main');
注意:
- 元素的Id是大小写敏感的,一定要写对元素的id。
- HTML文档中可能存在多个id相同的元素,则返回第一个元素。
- 只从文档中进行搜索元素,如果创建了一个元素并指定id,但并没有添加到文档中,则这个元素是不会被查找到的。
2.按照class查询
document.getElementsByTagName()
这个API是根据元素的class返回一个即时的HTMLCollection。
语法:
var elements = document.getElementsByClassName(names); // or:
var elements = rootElement.getElementsByClassName(names);
-
elements
是一个实时集合,包含了找到的所有元素。 -
names
是一个字符串,表示要匹配的类名列表;类名通过空格分隔。 -
getElementsByClassName
可以在任何元素上调用,不仅仅是document
。调用这个方法的元素将作为本次查找的根元素。
注意:
- 返回结果是一个即时的HTMLCollection,会随时根据文档结构变化。
- IE9以下浏览器不支持。
- 如果要获取2个以上
classname
,可传入多个classname
,每个用空格相隔。
3.按照Tag查询
document.getElementsByTagName()
返回一个包括所有给定标签名称的元素的HTML集合HTMLCollection。 整个文件结构都会被搜索,包括根节点。返回的 HTML集合是动态的, 意味着它可以自动更新自己来保持和 DOM 树的同步而不用再次调用document.getElementsByTagName()。
语法:
var elements = document.getElementsByTagName(name);
注意:
- 如果要对HTMLCollection集合进行循环操作,最好将其长度缓存起来,因为每次循环都会去计算长度,暂时缓存起来可以提高效率。
- 如果没有存在指定的标签,该接口返回的不是null,而是一个空的HTMLCollection。
-
name
是一个代表元素的名称的字符串。特殊字符 “*” 代表了所有元素。
4.按照name查询
document.getElementsByName(name)
getElementsByName
主要是通过指定的name
属性来获取元素,它返回一个即时的NodeList对象。
语法:
var elements = document.getElementsByName(name)
注意:
- 返回对象是一个即时的NodeList,它是随时变化的。
- 在HTML元素中,并不是所有元素都有
name
属性,比如div
是没有name
属性的,但是如果强制设置div
的name
属性,它也是可以被查找到的 - 在IE中,如果
id
设置成某个值,然后传入getElementsByName
的参数值和id值一样,则这个元素是会被找到的,所以最好不好设置同样的值给id
和name
。
5.通过选择器查询
(1)document.querySelector(selector)
document.querySelector
返回第一个匹配的元素,如果没有匹配的元素,则返回null
。
语法:
var element = document.querySelector(selectors);
(2)document.querySelectorAll(selectors)
返回的是所有匹配的元素,而且可以匹配多个选择符。
语法:
var element = document.querySelector(selectors);
-
elementList
是一个静态的NodeList
类型的对象。 -
selectors
是一个由逗号连接的包含一个或多个CSS选择器的字符串 - 如果
selectors
参数中包含CSS伪元素,则返回一个空的elementList
。
例子:
var matches = document.querySelectorAll("div.note, div.alert");
返回一个文档中所有的class
为"note"
或者"alert"
的div
元素。
注意:
- querySelectorAll也是通过深度优先搜索,搜索的元素顺序和选择器的顺序无关。
- 返回的是一个非即时的NodeList,也就是说结果不会随着文档树的变化而变化。
- 兼容性问题:
querySelector
和querySelectorAll
在ie8以下的浏览器不支持。
6.获取父元素
element.parentNode // 基本都兼容
7.获取子元素
element.childNodes // 基本都兼容
8.获取兄弟节点
获取前面的兄弟节点
element.previousSibling //基本都兼容
获取所有前面的兄弟节点就是遍历previousSibling
, 直到null
。
注意:
Gecko内核的浏览器会在源代码中标签内部有空白符的地方插入一个文本结点到文档中.因此,使用诸如 Node.firstChild 和 Node.previousSibling 之类的方法可能会引用到一个空白符文本节点, 而不是使用者所预期得到的节点。
获取后面的兄弟节点
element.nextSibling //基本都兼容
获取所有和注意点都和previousSibling
一样。
二、DOM操作
1.创建DOM
document.createElement(tagName)
2.新增DOM
添加到节点的子节点的最后
parentElement.appendChild(child)
添加到节点的前面
Element.insertBefore(newElement, Element)
通过insertBefore
方法可以将newElement
插入到Element
前面,如果Element
是null
则将newElement
插入到Element
的尾部。
如果newElement
是一个已经存在在文档中的DOM
, insertBefore
则会表现为移动该DOM
(将会保留所有的事件)。
添加到节点的后面
没有这个函数,可以使用 insertBefore 方法和 nextSibling 来模拟它。
parentDiv.insertBefore(sp1, sp2.nextSibling);
如果sp2
没有下一个节点,则它肯定是最后一个节点,则sp2.nextSibling
返回null
,且sp1
被插入到子节点列表的最后面(即sp2
后面)。
3.修改DOM
修改DOM的文案
// 获取标签内的所有内容 Element.innerText // 只获取标签内的文字内容,不包括标签
Element.innerHTML
修改css
element.style.cssAttribute
修改属性
element.setAttribute()
element.removeAttribute()
element.className
4.删除DOM
删除DOM
parentElement.removeChild(element)
清空子节点
没有专门的函数,可以遍历removeChild来实现
var element = document.getElementById("top");
while (element.firstChild) {
element.removeChild(element.firstChild);
}
三、事件
1.事件绑定API
绑定事件对象.addEventListener(事件类型,回调函数,布尔值)
- 如果不传布尔值或为false – fn就会走
冒泡阶段
。 - 如果布尔值为true-- fn 就会走
捕获阶段
。
element.addEventListener('click',function,Boolean)
2.事件委托
情景一
你要给100个按钮做监听事件,咋办?
情景二
你要监听目前不存在的元素的事件,咋办?
<!DOCTYPE>
<html>
<head>
<meta charset='UTF-8'>
<title>事件委托</title>
<head>
<body>
<div class='max'>
<button class='btn-1'>btn1</button>
<button class='btn-2'>btn2</button>
<button class='btn-3'>btn3</button>
.
. (省略96个button)
.
<button class='btn-100'>btn100</button>
</div>
<script>
/* 监听祖先元素 */
let btn_max=document.querySelector('.max');
btn_max.addEventListener('click',()=>{
const t = e.target; //为了保存e.target对象,因为它是一个异步的结果,点击后e.target对象就会消失。
if(e.tagName.toLowerCase()==='button'){
console.log('button被点击了');
console.log('被点击的button是'+ t.className); //这样就能知道点击了哪一个button
}
})
</script>
</body>
<html>