知识点
- DOM 本质
- DOM 节点操作
- DOM 结构操作
- DOM 性能
前言
各种框架层出不穷,但DOM操作一直都会是前端工程师的基础,必备知识。
只会Vue和React等框架,而不懂DOM操作的前端程序员们。。。
DOM的本质?
Do you know?
首先,先了解一下什么是xml
。 上代码:
XML (可扩展标记语言 EXtensible Markup Language)
XML 是一种标记语言, 被设计用来传输和存储数据,而非显示数据(HTML就被设计用来显示数据)
XML使用的标签没有被预定义,你需要自行定义标签。
SGML、HTML、XML、XHTML、HTML5 之间的关系,知道否?
HTML是一种特殊的XML。它遵循W3C的规定,各种规定,必须先写什么,怎么写什么。
那么如果是一个字符串对象(html一大坨)的话,让浏览器,js处理是非常不方便的。
如何查询,如何操作等等比较麻烦。所以浏览器拿到代码之后。。。
DOM可以理解为浏览器把拿到的html代码,结构化一个浏览器能识别并且js可操作的一个模型而已(也就是DOM结构树)
树结构什么的不要我讲了吧
DOM 节点操作
获取 DOM 节点
- 通过元素类型的方法来操作:
- **
document.getElementById();
//id名,在实际开发中较少使用,选择器中多用class id一般只用在顶级层存在 不能太过依赖id
** - **
document.getElementsByTagName();
//标签名
** - **
document.getElementsByClassName();
//类名
** - **
document.getElementsByName();
//name属性值,一般不用
** - **
document.querySelector();
//css选择符模式,返回与该模式匹配的第一个元素,结果为一个元素;如果没找到匹配的元素,则返回null
** - **
document.querySelectorAll()
//css选择符模式,返回与该模式匹配的所有元素,结果为一个类数组
**
注意:
- 前缀为document,意思是在document节点下调用这些方法,当然也可以在其他的元素节点下调用哦!
querySelector()
和querySelectorAll()
两个方法为静态的,不是实时的,保存的是当时的状态,是一个副本,即:在以后的代码中通过方法使所选元素发生了变化,但该值依然不会改变,因此使用有局限性,一般不用,除非就想得到副本
- 根据关系树来获取节点(遍历节点树):
根据前面,我们已经知道:DOM(文档对象模型)可以将任何HTML、XML文档描绘成一个多层次的节点树。所有的页面都表现为以一个特定节点为根节点的树形结构。html文档中根节点为document节点。
所有节点都有nodeType
属性,代表节点的不同类型,通过nodeType
属性可以来判断节点的类型。
经常使用的节点主要有以下几种类型:
- Element类型(元素节点):nodeType值为 1
- Text类型(文本节点):nodeType值为 3
- Comment类型(注释节点):nodeType值为 8
- Document类型(document节点):nodeType值为 9
其规定的一些常用的属性有:
document.body
document.head
分别为HTML中的<body>
<head>
document.documentElement
为<html>
标签
所有的节点都有 hasChildNodes()
方法,用来判断有无子节点 有一个或多个子节点时返回true
通过一些属性可以来遍历节点树:
parentNode
//获取所选节点的父节点,最顶层的节点为#documentchildNodes
//获取所选节点的子节点们firstChild
//获取所选节点的第一个子节点lastChild
//获取所选节点的最后一个子节点nextSibling
//获取所选节点的后一个兄弟节点 列表中最后一个节点的nextSibling
属性值为null
`previousSibling` //获取所选节点的前一兄弟节点 列表中第一个节点的`previousSibling`属性值为`null`
注意:
由于文档中的节点类型较多,遍历子节点的结果很多时候并不能得到我们想要的结果。
小心哦!!空文本也是文本节点!
使用遍历元素节点则很方便。
- 基于元素节点树的遍历(遍历元素节点树):
parentElement
//返回当前元素的父元素节点(IE9以下不兼容)children
// 返回当前元素的元素子节点firstElementChild
//返回的是第一个元素子节点(IE9以下不兼容)lastElementChild
//返回的是最后一个元素子节点(IE9以下不兼容)nextElementSibling
//返回的是后一个兄弟元素节点(IE9以下不兼容)previousElementSibling
//返回的是前一个兄弟元素节点(IE9以下不兼容)
注意:
这些获取节点的方式,返回值要么是一个特定的节点,要么是一个集合HTMLCollection,这个节点的集合是一个类数组。
HTML中的 attribute 和 JavaScript中的 property
attribute
**attribute
是HTML标签中定义的属性(修改html属性,会改变html结构),它的值只能是字符串。
attribute 有三个方法:setAttribute()
, getAttribute()
, removeAttribute()
**
property
property
是JavaScript为元素对象定义的属性(修改对象属性,不会体现到html结构中)property 属性可以看作 DOM 对象的键值对,用点操作符修改。它也可以和其他的 JavaScript 对象一样添加自定义的属性以及方法。property 的值可以是任何的数据类型,对大小写敏感。
attribute 和 property 共同拥有的属性
虽然Attribute和Property定义的属性分别在不同层面上,但是有以下几个属性是共享的:
id
class
lang
dir
title
自定义的 property 不会出现在 html 代码中,只存在 js 中。因此,ele.getAttribute(‘user1’) 结果为:null
html 标签的5个标准特性:id,title,lang,dir,className(在DOM中以property方式操作这几个特性会同步到html标签中)。所以即使在html中没有指定id、title等,也会默认赋予一个空串,通过property属性(点操作符)可以访问。 而除此之外在html中设置的其他属性是不能通过Property访问到的(除了attribute特有的属性)。因此,ele.user 结果为:undefined
注意:
有一些比较特殊的情况:
- input 元素的 value
用点操作符修改 value 值,并不会同步到 attribute 上;但是通过 setAttribute 修改属性值,会同步到 property 上。
- 表单
一些表单元素,对于这些特殊的 attribute 节点,只要存在该节点,对应的 property 就为true,disabled 类似
- href
attribute 取得是相对路径;property 取得是绝对路径。
建议:
尽量使用property,因为property可能会在js的一些机制中避免DOM的重新渲染,而attribute一旦改了html结构,则一定会引起DOM重新渲染。
以下两种情况用attribute:
- 自定义 attribute 标签,因为它不能同步到 property 上。
- 访问内置的 html 标签的 attribute,如 input 的 value(可以用来检验 value 值是否改变)
DOM 结构操作
- 新增/插入节点
- 获取子元素列表,获取父元素
- 删除子元素
各种DOM操作,请读者自由发挥,耍起来哟~~
一定要记得多敲敲!!!
示例:主要代码如下
DOM 性能
DOM 操作非常“昂贵”,避免频繁的DOM操作。
-
对DOM 查询做缓存
// 不缓存 DOM 查询结果 for (let = 0; i < document.getElementsByTagName('p').length; i++) { // 每次循环,都会计算 length, 频繁进行 DOM 查询 }
// 缓存 DOM 查询结果 const pList = document.getElementsByTagName('p') const length = pList.length for (let i = 0; i < length; i++) { // 缓存 length, 只进行一次 DOM 查询 }
-
将频繁操作改为一次性操作
const list = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到 DOM 结构中 const frag = document.createDocumentFragment()
for (let i = 0; i < 20; i++) { const li = document.createElement('li') li.innerHTML =
List item ${i}
}
// 都完成之后,再统一插入到 DOM 结构中 list.appendChild(frag)
console.log(list)
复习回顾
DOM 是哪种数据结构
- 树(DOM树)
DOM 操作的常用API
- DOM 节点操作
- DOM 结构操作
- attribute 和 property 操作
attribute 和 property 的区别
- attribute:修改html属性,会改变html结构
- property:修改对象属性,不会体现到html结构中
- 两者都有可能引起DOM重新渲染
一次性插入多个DOM节点,考虑性能
- 你可以翻上去再瞧瞧
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!