来源:慕课网的课程 coding.imooc.com/learn/list/…
我只是搬运工非原创
DOM 的本质
讲 DOM 先从 html 讲起,讲 html 先从 XML 讲起。XML 是一种可扩展的标记语言,所谓可扩展就是它可以描述任何结构化的数据,它是一棵树!
HTML 是一个有既定标签标准的 XML 格式,标签的名字、层级关系和属性,都被标准化(否则浏览器无法解析)。同样,它也是一棵树。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<p>this is p</p>
</div>
</body>
</html>我们开发完的 html 代码会保存到一个文档中(一般以.html或者.htm结尾),文档放在服务器上,浏览器请求服务器,这个文档被返回。因此,最终浏览器拿到的是一个文档而已,文档的内容就是 html 格式的代码。
但是浏览器要把这个文档中的 html 按照标准渲染成一个页面,此时浏览器就需要将这堆代码处理成自己能理解的东西,也得处理成 JS 能理解的东西,因为还得允许 JS 修改页面内容呢。
基于以上需求,浏览器就需要把 html 转变成 DOM,html 是一棵树,DOM 也是一棵树。对 DOM 的理解,可以暂时先抛开浏览器的内部因此,先从 JS 着手,即可以认为 DOM 就是 JS 能识别的 html 结构,一个普通的 JS 对象或者数组。
DOM 节点操作
获取 DOM 节点
var div1 = document.getElementById('div1') // 元素
var divList = document.getElementsByTagName('div') // 集合
console.log(divList.length)
console.log(divList[0])
var containerList = document.getElementsByClassName('.container') // 集合
var pList = document.querySelectorAll('p') // 集合prototype
DOM 节点就是一个 JS 对象,它符合之前讲述的对象的特征 —— 可扩展属性,因为 DOM 节点本质上也是一个 JS 对象。因此,如下代码所示,p可以有style属性,有className nodeName nodeType属性。注意,这些都是 JS 范畴的属性,符合 JS 语法标准的。
var pList = document.querySelectorAll('p')
var p = pList[0]
console.log(p.style.width) // 获取样式
p.style.width = '100px' // 修改样式
console.log(p.className) // 获取 class
p.className = 'p1' // 修改 class
// 获取 nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)attribute
property 的获取和修改,是直接改变 JS 对象,而 attribute 是直接改变 HTML 的属性,两种有很大的区别。attribute 就是对 HTML 属性的 get 和 set,和 DOM 节点的 JS 范畴的 property 没有关系。
var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name', 'juejin')
p.getAttribute('style')
p.setAttribute('style', 'font-size:30px;')DOM 树操作
新增节点
var div1 = document.getElementById('div1')
// 添加新节点
var p1 = document.createElement('p')
p1.innerHTML = 'this is p1'
div1.appendChild(p1) // 添加新创建的元素
// 移动已有节点
var p2 = document.getElementById('p2')
div1.appendChild(p2)
获取父元素
var div1 = document.getElementById('div1')
var parent = div1.parentElement
获取子元素
var div1 = document.getElementById('div1')
var child = div1.childNodes
删除节点
var div1 = document.getElementById('div1')
var child = div1.childNodes
div1.removeChild(child[0])DOM性能
DOM操作非常“昂贵”,避免频繁的DOM操作
对DOM查询做缓存
//不缓存DOM查询结果
for(let i =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 listNode=document.getElementById('list');
//创建一个文档片段,此时还没插入到DOM树中
const frag=document.createDocumentFragment()
//执行插入
for(let i=0;i<10;i++){
const li=document.createElement("li");
li.innerHTML="list item"+XMLDocument;
frag.appendChild(li)
}
//都完成后 再插入到DOM树中
listNode.appendChild(frag)问题
DOM 是哪种基本的数据结构?
树
DOM 操作的常用 API 有哪些
- 获取节点,以及获取节点的 Attribute 和 property
- 获取父节点 获取子节点
- 新增节点,删除节点
DOM 节点的 Attribute 和 property 有何区别
- property 只是一个 JS 属性的修改
- attr 是对 html 标签属性的修改
BOM
DOM 是浏览器针对下载的 HTML 代码进行解析得到的 JS 可识别的数据对象。而 BOM(浏览器对象模型)是浏览器本身的一些信息的设置和获取,例如获取浏览器的宽度、高度,设置让浏览器跳转到哪个地址。
- navigator
- screen
- location
- history
// navigator
var ua = navigator.userAgent//浏览器信息
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
// screen
console.log(screen.width)
console.log(screen.height)
// location
console.log(location.href)
console.log(location.protocol) // 'http:' 'https:' 协议
console.log(location.pathname) // '/learn/199'
console.log(location.search)
console.log(location.hash)
// history
history.back()
history.forward()