JS Advance --- DOM

102 阅读3分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

浏览器是用来展示网页的,而网页中最重要的就是里面各种的标签元素,JavaScript很多时候是需要操作这些元素的

比如修改页面中的数据,或者将服务器请求过来的数据渲染到页面上(前端渲染)

此时我们就需要浏览器提供对应的可以被JS操作的数据模型,当我们操作数据模型的之后,浏览器会去修改对应的元素

为此浏览器提供了Document Object Model(DOM,文档对象模型) [DOM其实本质上是BOM的一部分]

我们可以使用JS来操作这些模型从而来修改我们的web界面

所以我们可以认为DOM是JS和网页文档之间沟通的桥梁

IiziQp.png

图上提供的是对应的类,当浏览器去解析Document的时候,会自动通过这些类去创建对应的实例对象

所以我们实际操作的其实是他们对应的实例

Node

在整个document中,每一个标签,文本,注释和属性都可以看成是一个个的节点(node)

所以在DOM中,所有元素的父类就是node,将所有节点共有的属性和方法抽离出来,放到node上

// 获取元素
const dvElem = document.querySelector('.box');

// 如果是标签,那么就是大写的标签名
console.log(dvElem.nodeName) // => DIV

// 标签的nodeType为1
console.log(dvElem.nodeType) // => 1

// 标签没有内容
console.log(dvElem.nodeValue) // => null

// childNodes可以获取所有的子节点 --- 类型是nodeList --- 伪数组
const textNode = dvElem.childNodes[0]

// 文本节点 节点名为 #text 类型为3, 值为文本内容(包含换行和空格)
console.log(textNode.nodeName) // => #text
console.log(textNode.nodeType) // => 3
console.log(textNode.nodeValue) // => lorem
const dvElem = document.querySelector('.box');

// 创建元素
const child = document.createElement('div')

// 设置节点内容
child.textContent = 'lorem'

// 挂载子节点
dvElem.appendChild(child)
// 注意: document是继承于node的
// 所以原则上document是存在appendChild方法的
// 但是浏览器做了限制,不允许document调用appendChild
// 因为document.appendChild所加的元素在html标签后
// 这是不合理的
// 所以我们一般使用document.body来在网页最后添加对应的内容
const dv = document.createElement('div')
dv.textContent = 'foo'
document.body.appendChild(dv)

document

console.log(document.body) // => body元素
console.log(document.documentElement) // => html元素
console.log(document.children[0]) // => html元素
console.log(document.childNodes[0]) // => 整个网页对象
console.log(document.title) // => 网页title内容
console.log(document.head) // => head元素
console.log(document.location === location) // => true document上也有location对象
// 创建元素
const el = document.createElement('image')
// 上述代码实际等价于
// const el = new HTMLImageElement()

// 获取元素
document.getElementById('foo') // 根据id来获取元素
document.getElementsByClassName('foo') // 根据class名获取元素 --- 结果为伪数组
document.getElementsByTagName('div') // 根据标签名来获取元素
document.getElementsByName("title") // 根据元素上的name属性的值去获取元素 --- 结果为伪数组
document.querySelector('.foo') // 根据选择器去获取元素 --- 取到的是第一个符合条件的元素
document.querySelectorAll('.foo') // 根据选择器去获取所有符合条件的元素

element

我们平时创建的div、p、span等元素在DOM中表示为Element元素

const el = document.querySelector('.box')

console.log(el.id) // 输出元素的id属性,如果元素没有id属性,那么值为空字符串
console.log(el.tagName) // => DIV
console.log(el.children) // 获取所有的子元素
console.log(el.className) // 获取元素的样式名 --- 字符串形式
console.log(el.classList) // 获取元素的样式名 ---- 伪数组形式
console.log(el.clientWidth) // 元素宽度 无边框
console.log(el.offsetWidth) // 元素宽度 有边框
console.log(el.offsetLeft) // 元素距离视口左边的距离
const el = document.querySelector('.box')

// 获取属性
const attrs = el.getAttribute('class')

// 设置属性
el.setAttribute('data-attr', 'custom attr')

// 获取自定义属性列表(以data-开头的属性)
console.log(el.dataset) // 值为一个map对象
// key是没有data-的属性名
// value是对应的属性值