冷门 API 尝试

220 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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 作为性能优化手段。

www.yuque.com/go/doc/5530…

二、关于 HTML

待补充。

三、关于 CSS

1. getComputedStyle() 获取元素的最终样式

该方法返回元素的计算样式。接受两个参数:

  • element 获取目标
  • pseudo-element 是否要联通伪元素一起获取,不需要时传入 null。
let dom = document.querySelector('.achens')

cosnole.log(getStyleByAttr(dom, null))

与 .style 的区别:

  1. .style 获取的是元素内联样式,而 getComputedStyle 获取的是最终样式(包含内联样式、嵌入样式和外部样式)
  2. .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

四、其它

待补充。**