目录
5 DOM节点的property 与attribute 区别
6 web- BOM BOM(Browser Object Model)-> 浏览器对象模型
前言
◆vue和React框架应用广泛,封装了DOM操作
◆但DOM操作- -直都会前端 工程师的基础、必备知识
◆只会vue而不懂DOM操作的前端程序员,不会长久
1 题目:
-
DOM 是哪种数据结构
-
DOM 操作常用 API
-
attr 和 property 的区别
-
一次性插入多个 DOM 节点,考虑节点
1 DOM 本质
DOM 本质:DOM本质(Document Object Model)
xml -> html ->
DOM是html语言解析出来的一棵树
从 HTML 说起,先从XML说起,XML 是一种可扩展的标记性语言,描述的是一棵树,可以自定义标签,类似于 JSON,区别在于JSON的表现形式与这个不太一样,XML 历史比 JSON 早,JSON 这种结构天生跟 JS 的数据结构相吻合,后来发展的很快。 HTML 也是一种特定的 XML,规定了一些特定的名称。因此 DOM 本质是一棵树,首先 HTML本身是一个树形的结构,HTML 是文件或者是代码,DOM 是浏览器内存中初始化好的树。DOM 本质是从 HTML 语言中浏览器解析出来的一棵树 DOM 节点的操作: DOM 结构操作: DOM 性能:
2 DOM 节点操作
获取节点、nodeName、nodeType、attribute、property
获取DOM节点
(document.getElementsById元素、
getElementsByTagName集合、
getElementsByClassName集合、
getElementsByName集合、
querySelectorAll集合(CSS选择器)、
querySelector元素、
document.documentElement元素html
document.body元素body
...)
attribute
修改html属性,会改变html结构(自定义属性,原有属性 都会触发)
const pList = document. querySelectorAll('p')
const p = pList[0]
p.setAttribute('data-name','imooc')
p.getAttribute('data-name')
p.setAttribute('style','font-size:50px;')
p.getAttribute('style')
property
修改JS对象属性,不会体现到html结构中(自定义属性不会触发,其它原有属性需要同步dom样式的还是会体现在html结构中的);如下:
const pList = document. querySelectorAll('p')
const p = pList[0]
console. log(p.style.width) // 获取样式
p. style.width = ' 100px' //修改样式
console. log(p.tlassName) // 获取class
console. log(p. nodeName )
console. log(p. nodeType)
3 DOM结构操作
新建节点、插入节点、获取父节点、获取子节点、删除节点
这里要注意 appendChild 不仅可以插入节点还可以移动节点
新增/插入节点
const div1 = document.getElementById('div1')
const div2 = document.getElementById('div2')
//新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is newP'
//插入节点
div1.appendChild(newP)
//移动节点
const p1 = document.getElementById('p1')
div2.appendChild(p1)
获取子元素列表,获取父元素
const div1ChildNodes = div1.childNodes
cosnole.log(div1.childNodes)
const div1ChildNodesP= Array.prototype.slice.call(div1.childNodes).filter(child => {//过滤
if(child.nodeType === 1) {//获得正常DOM节点。而不是text节点
return true
}
return false
})
cosnole.log('div1ChildNodesP',div1ChildNodesP)
console.log(p1.parentNode)
删除子元素
div1.removeChild(div1ChildNodesP[0])
DOM 节点的 property:可以用 JS 来操作节点的一些属性,比如 style className 等
DOM 节点的 attribute:可以操作 DOM 属性改变页面,也可以加一些自定义属性,可以在 DOM 结构中看到自定义的属性
4 DOM性能
DOM操作是非常昂贵的,要避免频繁的DOM操作
对DOM查询做缓存(变量接收)
将频繁操作改为一次性操作
document.createDocumentFragment()
5 DOM节点的property 与attribute 区别
property:能够获取DOM元素,通过JS属性来修改(比如style className等)
attribute:通过getAttribute,setAttribute直接修改HTML的结构
property修改的是JS变量的属性
attribute修改的是标签的属性
区别:
property:修改对象的属性,不会体现到html结构中(推荐)
attribute:修改html属性,会改变html结构(必须修改标签结构的情况)
两者都可能引起DOM重新渲染
建议:尽量用 property 操作,因为property可能会在JS机制中,避免一些不必要的DOM渲染;但是attribute是修改HTML结构,一定会引起DOM结构的重新渲染,而DOM重新渲染是比较耗费性能的
6 web- BOM BOM(Browser Object Model)-> 浏览器对象模型
没有任何难度,随用随查,面试比较少
属性:
-
navigator:浏览器信息
-
screen:屏幕信息
-
location:url信息
-
history:历史记录信息
navigator(浏览器信息):
-
userAgent - 浏览器类型
-
...
screen(屏幕信息):
-
width - 屏幕宽度
-
height - 屏幕高度
-
...
location(url信息):
-
href - 当前网址
-
protocal - 网址协议
-
host - 域名
-
pathname - 路径
-
search - 查询参数
-
hash - hash 值
-
...
history(历史记录信息):
-
back() - 后退
-
forword() - 前进
-
...
题目:
-
编写一个通用的事件监听函数
-
描述事件冒泡的流程
-
无限下拉的图片列表,如何监听每个图片的点击
7 编写一个通用的事件监听函数
8 描述事件冒泡的流程
事件代理
代码简洁
减少浏览器内存占用
但是,不要滥用
9无限下拉的图片列表,如何监听每个图片的点击
代码简洁
减少浏览器内存占用
不要滥用(适用于‘无限下拉的图片列表,如何监听每个图片的点击’)
function bindEvent(ele, type, selector, fu) {
if (fn == null) {
fn = selector
selector = null
}
ele.addEventListener(type, event => {
const target = event.target
if (selector) {
//代理
if (target.matches(selector)) {
fn.call(target, event)
}
} else {
// 普通绑定
fn.call(target, event)
}
})
}
bindEvent(div3, 'click','a', event => {
event.preventDefault()
alert(event.target.innerHTML)
})
-
获取触发的元素
event.target(event.target代表的是触发事件的元素,而event.currentTarget代表的是那个绑定了事件处理函数的元素。区别)
-
阻止默认行为
event.preventDefault()
-
阻止冒泡
event.stopPropagation()
10 事件代理(必考) 是什么:
是什么: 基于事件冒泡实现的事件绑定,将子元素触发的事件交给父元素的事件处理函数处理. 作用 : 多个元素需要同事件同事件处理函数 ;//不要滥用 优点 : 代码简洁; 减少浏览器内存占用 (因为dom事件是由web apis 管理的,触发时将事件添加到回调栈中执行)
事件代理:通过冒泡机制,在祖先元素上绑定事件,然后通过 e.target 来判断是哪个元素触发的事件
事件
流程:
事件的处理过程主要有三个阶段:捕获、目标、冒泡
-
捕获阶段:用户操作,window派发该事件不断经过下级节点到目标节点的过程
-
目标阶段:派发事件到达目标节点,触发该事件
-
冒泡阶段:触发事件后,由目标元素逐级向上传递
事件对象(event):
-
target - 事件触发对象
-
preventDefault() - 取消默认行为
-
stopPropagation() - 阻止冒泡
事件冒泡:
-
基于 DOM 树形结构
-
事件会顺着触发元素网上冒泡
-
应用场景:代理
事件代理:
基于事件冒泡,指定一个事件处理程序,就可以管理某一类型的所有事件,从而减少DOM交互提高性能
-
代码简洁(不用每个元素都绑定事件)
-
减少浏览器内存占用(不需要每个元素都添加事件监听)
-
不要滥用(适用于元素数量太多、结构复杂不好每个元素都绑定事件的场景)
通用事件绑定函数:
function bindEvent(elem, type, seletor, fn) {
if(fn == null) { // 兼容只传入3个参数的情况
fn = seletor;
seletor = null;
}
elem.addEventListener(type, event => {
const target = event.target;
if(seletor) { // 使用事件代理
// matches:判断当前DOM节点是否能完全匹配对应的css选择规则器
if(target.matches(seletor)) {
// 改变this指向,使得函数调用时,如this.innerHTML类似代码,this指向正确
fn.call(target, event);
}
} else { // 普通事件绑定
fn.call(target, event);
}
})
}
// 使用
const div = document.getElementById('div');
bindEvent(div, 'click', 'a', function (event) {
console.log(this.innerHTML); // 若使用this,则回调函数不能是箭头函数
console.log(event.target.innerHTML); // 若使用箭头函数
})
总结:
- DOM 是哪种数据结构:DOM本质(Document Object Model)DOM是html语言解析出来的一棵树(数据结构)
- DOM 节点操作:获取DOM节点 getElementsByTagName ,attribute修改html属性 ,property修改JS对象属性
- DOM结构操作: 新建节点、插入节点、获取父节点、获取子节点、删除节点createElement\innerHTML getElementById appendChild removeChild
- DOM操作是非常昂贵的,要避免频繁的DOM操作 将频繁操作改为一次性操作document.createDocumentFragment() (Fu ruai ge)
- DOM节点的property 与attribute 区别:property:能够获取DOM元素,通过JS属性来修改(比如style className等)
- attribute:通过getAttribute,setAttribute直接修改HTML的结构
- property修改的是JS变量的属性 attribute修改的是标签的属性
- 事件冒泡: 基于 DOM 树形结构 ,事件会顺着触发元素网上冒泡 到document为止
- 阻止冒泡 event.stopPropagation() 阻止默认行为event.preventDefault()
- 事件代理 :通过冒泡机制,在祖先元素上绑定事件,然后通过 e.target 来判断是哪个元素触发的事件
- 基于事件冒泡,指定一个事件处理程序,就可以管理某一类型的所有事件,从而减少DOM交互提高性能代码简洁(不用每个元素都绑定事件)减少浏览器内存占用(不需要每个元素都添加事件监听
关于事件捕获和事件冒泡的顺序,以及如何处理事件冒泡带来的影响_strongest强的博客-CSDN博客_事件捕获和事件冒泡顺序