携手创作,共同成长!这是我参与「掘金日新计划 · 9 月更文挑战」的第11天,点击查看活动详情 >>
一、关于 JS
1. MutationObserver 监听 DOM 是否发生变化
用于监听 DOM 元素是否发生变化。其接受一个回调函数为参数,且这个回调函数返回
- mutationsList参数来记录节点的变化。
- observer 来构造 MutationObserver 对象。
其中,MutationObserver 对象还有三个方法:
-
- observer:设置监听目标:
-
-
- target:监听目标。
- options:监听目标时的配置选项。
-
-
-
-
- childList:为 True 时,表示开始监听子元素的添加和删除,但不包括子元素的修改和子节点的后代变化。
- attributes:为 True 时表示目标属性的改变也会被监听。
- characterData:为 True 时表示监听目标的数据变化。
- subtree:为 True 时表示目标及目标的后代都会被监听。
- attributeOldValue:默认为 True,表示需要记录监听目标改变前的属性值。(此属性为 True 时可以省略 attributes 属性)
- characterDataOldValue:默认为 True,表示需要记录监听目标改变之前的数据。(此属性为 True 时可以省略 characterData 属性)
- attributeFilter:在 attributes 为 True 或者没设置的时候,设置一个需要监听的属性数组。
-
-
-
- disconnect:关闭观察。
- takeRecords:清空记录的所有节点变化。
//选择一个需要观察的节点
var targetNode = document.getElementById('root')
// 设置 observer 的配置选项
var config = { attributes: true, childList: true, subtree: true }
// 当节点发生变化时的需要执行的函数
var callback = function (mutationsList, observer) {
for (var mutation of mutationsList) {
if (mutation.type == 'childList') {
console.log('A child node has been added or removed.')
} else if (mutation.type == 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.')
}
}
}
// 创建一个 observer 示例与回调函数相关联
var observer = new MutationObserver(callback)
// 使用配置文件对目标节点进行观测
observer.observe(targetNode, config)
// 停止观测
observer.disconnect()
Tips: MutatinObserver 是个异步任务,它会把 DOM 变动记录封装成一个数组进行处理,而不是一个个的处理 DOM 变动。在
在被触发后 MutationsObserver 不会立刻执行,而是等到所有 DOM 操作都结束后才可以是执行相应回调事件。
2. IntersectionObserver 得知某个 DOM 是否进入视口
用作监听元素是否已经进入可视区,接受两个参数:
- callback 在元素进入和离开可视区域时触发。该回调函数可接受两个参数:
-
- entries:是一个数组,该数组中的每一项都是一个 IntersectionObsrverEntry 对象,如果同时有两个被监听对象发生改变时,entries 数组就会有连个成员,其中每个成员都有含有以下属性:
-
-
- time:进入或离开可视区域的时间戳,单位为毫秒。
- target:被监听的目标元素。
- isIntersecing:目标元素是否可见。
- rootBounds:根元素的矩形区域信息,相当于 getBoundingClientRect() 方法的返回值,如果没有根元素,则返回 null。
- boundingClientRect:目标元素的矩形区域的信息。
- intersectionRect:目标元素与视口的交叉信息。
- intersectionRatio:目标元素的可见比例,即 intersectionRect 占 boundingClientRect 的比例,完全可见时为 1,完全不可见时小于等于 0。
-
-
- self:代表 IntersectionObserver 自身,可以在回调内使用该参数解除观察。
- option 配置选项:
IntersectionObserver(callback, option)
var io = new IntersectionObserver((entries) => {
console.log(entries)
})
// 开始观察,观察多个目标,就需要多次调用这个方法
io.observe(document.getElementById('example'))
io.observe(document.getElementById('achens'))
// 停止观察
io.unobserve(element)
// 关闭观察器
io.disconnect()
扩展 1. 实现图片懒加载
// 获取所有带有图片标签
const imgs = document.querySelectorAll('img')
// 定义 IntersectionObserver 配置信息
const config = {
rootMargin: '0px',
threshold: 0
}
// 创建 IntersectionObserver 实例对象
let observer = new IntersectionObserver((entries, self) => {
// 拿出所有发生变化的元素
entries.forEach((entry) => {
// 判断这个元素是否处于可见状态
if (entry.isIntersecting) {
// 如果是的话,则开始替换图片 URL 实现图片懒加载
let img = entry.target
let src = img.dataset.src
if (src) {
img.src = src
img.removeAttribute('src')
}
// 解除观察
self.unobserve(entry.target)
}
})
}, config)
// 将所有 img 标签加入观察列表
imgs.forEach((image) => {
observer.observe(image)
})
扩展 2. 实现无限滚动
// 创建 IntersectionObserver 实例
let observer = new IntersectionObserver(function (entries) {
// 判断触发元素是否可见,如果不可见就直接返回不做任何操作
if (entries[0].intersectionRatio <= 0) return
// 可见时调用图片加载方法,具体逻辑这里省略
loadItems(10)
})
// 开始观察
observer.observe(document.querySelector('.scrollerFooter'))
3. requestAnimationFrame 执行一个动画
其作用类似 setInterval(),都是循环执行回调函数。
requestAnimationFrame(callback)
requestAnimationFrame 可以根据屏幕的刷新率计算并在最好的回调函数执行时机来执行 callback。
requestAnimationFrame 能做的就是保证屏幕的每一次刷新间隔中执行一次回调函数,使其不会出现丢帧现象,也不导致动画出现卡顿的问题。
示例:这篇文章中使用了 requestAnimationFrame 作为性能优化手段。
二、关于 HTML
待补充。
三、关于 CSS
1. getComputedStyle() 获取元素的最终样式
该方法返回元素的计算样式。接受两个参数:
- element 获取目标
- pseudo-element 是否要联通伪元素一起获取,不需要时传入 null。
let dom = document.querySelector('.achens')
cosnole.log(getStyleByAttr(dom, null))
与 .style 的区别:
- .style 获取的是元素内联样式,而 getComputedStyle 获取的是最终样式(包含内联样式、嵌入样式和外部样式)
- .style 可读可写,而 getComputedStyle 只可以获取。
2. getBoundingClientRect() 获取元素的大小和位置
该方法返回一个 DOMRect 对象,该对象是由元素的 getClientRects() 方法返回的一组矩形的集合。该集合中包含元素的 width,height,left,top,right,bottom,x,y 等属性,且是只读的。
其中除了 width,height 意外属性都是相对于试图窗口的左上角来计算的。
let dom = document.querySelector('.achens')
let domRect = dom.getBoundingClientRect()
console.log(domRect)
示例:
获取元素相对于左上角定位的距离。
let dom = document.querySelector('.achens')
let positionX = dom.getBoundingClientRect().left +
document.documentElement.scrollLeft
let positionY = dom.getBoundingClientRect().top +
document.documentElement.scrollTop
四、其它
待补充。**