ResizeObserver
ResizeObserver 接口可以监听到 Element 的内容区域或 SVGElement的边界框改变。内容区域则需要减去内边距padding。
也就是说,ResizeObserver是可以监听到DOM元素,宽高的变化,需要注意的一点就是监听出变化结果是contentBox的宽度和高度。
ResizeObserver 与 resize对比
1、ResizeObserver 性能比 resize 好
(1)对于窗口大小改变也可以用 addEventListener 监听 resize 事件,但由于reize 事件会在一秒内触发将近60次,很容易在改变窗口大小时导致性能问题;所以window.resize事件通常是很消费性能的
(2)resize 是全局监听,它会监听每个元素的大小变化而不是具体到某个元素(只有window对象才有resize事件);ResizeObserver 只会监听某个指定的元素。
(3)ResizeObserver 在每帧绘制之前触发,确保所有的布局和重绘操作可以在一帧的生命周期内完成。这使得回调函数的执行能够更加及时,避免了额外的重绘和布局计算,从而提高性能。
2、避免死循环
(1)避免了通过回调函数调整大小时,创建的无限回调循环和循环依赖项
(2)ResizeObserver 在浏览器开始绘制之前确保处理完所有的调整和重排,从而避免了布局抖动(layout thrashing)和不必要的性能损耗。因此,在当前帧的生命周期内,所有的尺寸变化处理(包括回调)都会发生,而不是推迟到下一帧。
3、监听多样化
非仅限于窗口大小变化。可以监听 Element 的内容区域、SVGElement 的边界框改变、某个节点的出现和隐藏
自定义指令实现 小Demo自定义滚动条
class为resize的div 宽高用百分比,不然监听不到高度变化
html代码
<template>
<div class='resize' v-resize>
<p>元素宽度变化 小于600时出现横向滚动条:{{ screenWidth }}</p>
<p>元素高度变化 小于300时出现纵向滚动条:{{ screenHeight }}</p>
</div>
</template>
<style lang='less' scoped>
.resize{
padding: 20px;
width: 70%;
height: 50%;
border: 1px solid #ccc;
p{
width: 700px;
height: 200px;
}
}
</style>
js代码
export default {
name: '',
data(){
return {
screenWidth:0,
screenHeight:0,
}
},
created(){},
mounted(){},
methods: {},
directives:{
resize:{
inserted(el,binding,vnode){
// vnode 可以访问到data里的值
const resize = new ResizeObserver((entries)=>{
// 宽高去取四舍五入整数部分
const width = Math.round(entries[0].contentRect.width)
const height = Math.round(entries[0].contentRect.height)
vnode.context.screenWidth = width
vnode.context.screenHeight = height
if(width<=600){
el.style.overflowX = "scroll"
}else{
el.style.overflowX = "hidden"
}
if(height<=300){
el.style.overflowY = "scroll"
}else{
el.style.overflowY = "hidden"
}
console.log(width)
console.log(height)
})
resize.observe(el)
}
}
}
}
</script>
当宽大于600时,高大于300时是没有滚动条的
当宽小于600时,高小于300时就会出现滚动条