这是我参与更文挑战的第 10 天,活动详情查看:更文挑战
众所周知,window 有 resize 事件,可以通过 resize 事件做一些特殊的事情。但这个事件对普通的 HTML 元素,是不支持的。这给 echarts 图表自适应的场景带来了麻烦。
本文介绍几种简单的方式,来解决上述问题。
1. 使用 ResizeObserver
使用方法
- 确定想要被监听的元素 box
- 确定当被监听的元素尺寸发生变化时触发事件 onResize
- 使用 ResizeObserver 创建监听
const observer = new ResizeObserver(onResize).observe(box)
- 当页面或组件被销毁时断开监听(非必须)
observer.disconnect()
实例
兼容性:现代浏览器均支持
2. 使用 relative + 100% + iframe/object
使用方法
- 将被监听的元素 box 设置为 relative,或者在元素外面增加一层元素 box,将外层元素设置为 relative,同时设置内层元素充满 box
- 创建一个 iframe 或者 object,令该元素的 id 为 helper。设置属性为 absolute,width 和 height 均为 100%,充满 box,并设置 visibility 为 hidden。这一步的操作
- 确定当被监听的元素尺寸发生变化时触发事件 onResize
- 监听 iframe 或 object 的 window 的 resize 事件,在事件回调中执行 onResize 方法
实例
兼容性:IE 也支持
在 IE11 下,使用 object 时会层叠在 box 内的元素上层,即使设置 z-index 的值为最低。这种情况下建议 transform 到可视区域外,或者仅使用 iframe。iframe 没有这个问题。
3. 使用定时器定期查询
使用方法
- 确定想要被监听的元素 box
- 确定当被监听的元素尺寸发生变化时触发事件 onResize
- 使用定时器 setInterval 循环查询 box 的 size,和上次储存的值比较,当不同时调用 onResize 方法
实例
兼容性:IE 也支持
但使用 setInterval 进行轮询,每次获取尺寸时,都触发了一次重绘操作,这增加了浏览器的性能压力。
总结
- 如果考虑对现代浏览器的支持,使用 ResizeObserver 最稳妥,就算是不支持的浏览器,可以使用 polyfill
- 如果不想使用 polyfill,可以使用第二种方案 iframe。但第二种方案对 dom 结构有限制
- 既然有了上面两种方式,定时器的方式就不需要了。相对前两种,对性能的影响较大