ResizeObserver API

当我们需要知道一个元素的大小变化或者屏幕横竖屏时,我们需要监听window.resize事件或者window.orientationchange方法。由于reize事件会在一秒内触发将近60次,所以很容易在改变窗口大小时导致性能问题;并且window.resize事件只有在window对象上才有,而不是具体到某个元素的变化。而ResizeObserver API就可以帮助我们:监听一个DOM节点的变化,这种变化包括但不仅限于:

  • 某个节点的出现和隐藏
  • 某个节点的大小变化

ResizeObserver API是一个新的JavaScript API,实际上,ResizeObserver API使用了观察者模式,也就是我们常说的发布-订阅模式。

浏览器兼容性:

虽然可以用来替代resize事件。但是它,很新,新到只有部分浏览器支持。
在这里插入图片描述
但是不要怂呀,如果想使用它,可以使用其polyfill。最低可以兼容到IE8以上的浏览器啦。所以以后在开发过程中如果想使用resize事件监听DOM的大小变化时,何不尝试一下ResizeObserver API呢?

import ResizeObserver from 'resize-observer-polyfill';

用法:

使用ResizeObserver API非常简单。ResizeObserver是个构造函数。在使用new关键字调用构造函数,返回实例对象时,需要传入一个回调函数,这个回调用于监听实例对象某个DOM节点的变化。如

 	  const myObserver = new ResizeObserver(entries => {
        entries.forEach(entry => {
          console.log('大小位置', entry.contentRect)
          console.log('监听的DOM', entry.target)
        })
      })
      myObserver.observe(document.body)

以上,调用实例对象的observe方法,监听整个body节点的变化,当改变窗口大小或者某个DOM节点出现或隐藏时时,就会触发回调。
在这里插入图片描述
触发回调后的第一个参数是一个ResizeObserverEntry对象。这里的entry.target是DOM节点本身,而entry.contentRect是一个对象,包含了节点的位置属性,如width, height, left, right, bottom, left, x, y等。

  • width:指元素本身的宽度,不包含padding,border值

  • height:指元素本身的高度,不包含padding,border值

  • top:指padidng-top的值

  • left:指padding-left的值

  • right:指left + width的值

  • bottom: 值top + height的值

  • x:大小与top相同,y:大小与left相同,不知道具体是指什么

明白了contentRect之后,就可以在使用这个api的时候针对不同场景获取不同的值进行业务的开发。

接着,如果想在监听多个DOM节点的变化,直接在一个实例对象上调用多次observe方法就好了。如:

const myObserver = new ResizeObserver(entries => {
// 注意,entres是个数组,数组项为每个需要监听的DOM节点
   entries.forEach(entry => {
     console.log('大小位置 contentRect', entry.contentRect)
     console.log('监听的DOM target', entry.target)
   })
})
myObserver.observe(document.body)
myObserver.observe(document.querySelector('#app'))

实例对象myObserver方法除了有observe方法之外,还有disconnect方法和unobserve方法。

unobserve方法,顾名思义了,就是取消监听某个DOM节点。比如说想在两秒后取消监听document.body,那么这样做就好了

window.setTimeout(() => {
   myObserver.unobserve(document.body)   // 需要接收一个参数
}, 2000)

disconnect方法呢,就是取消对所有节点的监听。比如说想在四秒后取消监听所有节点,那么

window.setTimeout(() => {
   myObserver.disconnect()    // 此时就不会再监听document.body,和#app节点了
}, 4000)

最后,在使用ResizeObserver API的时候,在每次触发元素的大小变化时,会在1s内触发回调蛮多次的。如果想进一步优化性能,可以加上throttle节流函数处理

// throttle需要自行引入哈
const myObserver = new ResizeObserver(throttle(entries => {
  entries.forEach(entry => {
    console.log('大小位置 contentRect', entry.contentRect)
    console.log('监听的DOM target', entry.target)
  })
}), 500)

这样子就能做到每个500ms触发一次回调啦。是不是很劲(粤语)


使用示例补充:

// 导入兼容模块
import ResizeObserver from 'resize-observer-polyfill';
const element1 = document.getElementById('div1');
const element2 = document.getElementById('div2');
/* 
 *  新建以一个观察者,传入一个当尺寸发生变化时的回调处理函数
 *  参数entries 是 ResizeObserverEntry 的数组,包含两个属性:
 *  ResizeObserverEntry.contentRect   包含尺寸信息(x,y,width,height,top,right,left,bottom)
 *  ResizeObserverEntry.target  目标对象,即当前观察到尺寸变化的对象
 *
 */
const robserver = new ResizeObserver( entries => {
  for (const entry of entries) {
     // 可以通过 判断 entry.target得知当前改变的 Element,分别进行处理。
     switch(etry.target){
       case element1 :
          entry.target.innerHTML = `第一个DIV尺寸 [${entry.contentRect.width} : ${entry.contentRect.height}]`;
       break;
       case element2 :
          entry.target.innerHTML = `第二个DIV尺寸 [${entry.contentRect.width} : ${entry.contentRect.height}]`;
       break;
     }
  }
});
robserver.observe(element1);
robserver.observe(element2);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值