如题,第一反应:
window.addEventListener("resize",handler,useCapture)
简单粗暴,但缺点也明显:文档视图调整大小时会触发resize事件,针对的 仅是window,而普通的DOM元素没有 onresize 事件的。
所以,对普通的DOM元素进行尺寸大小变化的监听,抛弃错误的第一感觉,可选择以下方法:
ResizeObserver
ResizeObserver
属于Web API
可以监听到
Element
的内容区域或SVGElement
的边界框改变 —— MDN ResizeObserver
通过构造器函数,new ResizeObserver(callback)
,创建并返回一个ResizeObserver对象,接着:
进行观察
ResizeObserver.observe(target,options)
开始观察指定dom
支持设置观察者将以哪种盒子模型来观察:指定options参数的box属性,可选值有content-box (默认值),border-box,和 device-pixel-content-box。传送门
结束观察
ResizeObserver.disconnect()
取消和结束所有目标dom的观察
ResizeObserver.unobserve(target)
取消和结束指定dom的观察
示例
<script>exportdefault{methods:{handleResize(){console.log("handleresize");}},mounted(){constdom=this.$refs.target.$el;//假设this.$refs.target返回是VueComponent对象this.observer=newResizeObserver(this.handleResize);this.observer.observe(dom,{box:"border-box"});},beforeDestroy(){this.observer.disconnect();}};</script>
什么时候触发执行callback的?
初始化执行一次
文档视窗改变大小会执行
元素发现尺寸改变(非2导致)会执行
resize-observer-polyfill
ResizeObserver存在一定的浏览器兼容问题,详见 can i use
该npm包的定位是:
A polyfill for the Resize Observer API.
基于MutationObserve或Mutation Events实现:为了解决ResizeObserver API的浏览器兼容问题
(请注意:在 IE10 及更低版本中存在样式问题)
示例
Element UI的走马灯
和隐藏组件:滚动条
//https://github.com/ElemeFE/element/blob/dev/src/utils/resize-event.jsimportResizeObserverfrom'resize-observer-polyfill';import{debounce}from'throttle-debounce';exportconstaddResizeListener=function(element,fn){if(isServer)return;if(!element.__resizeListeners__){element.__resizeListeners__=[];element.__ro__=newResizeObserver(debounce(16,resizeHandler));element.__ro__.observe(element);}element.__resizeListeners__.push(fn);};//https://github.com/ElemeFE/element/blob/dev/packages/scrollbar/src/main.jsimport{addResizeListener,removeResizeListener}from"@/utils/resize-event";mounted(){!this.noresize&&addResizeListener(this.$refs.resize,this.update);}
element-resize-detector
同resize-observer-polyfill,也是可监测DOM元素大小变化的npm包
定位是:
Optimized cross-browser resize listener for elements.
性能有所提升,用法类似ResizeObserver API
开始监听
listenTo(element,listener)或listenTo(options,element,listener)
结束监听
removeListener(element,listener)或removeAllListeners(element)或uninstall(element)
示例
<script>importelementResizeDetectorMakerfrom"element-resize-detector";exportdefault{methods:{handleResize(){console.log("doresize");}},mounted(){//MustbeaDOMelementoracollectionofDOMelements.constdom=this.$refs.col.$el;this.observer=elementResizeDetectorMaker();this.observer.listenTo({strategy:"scroll"},//基于滚动的情况下,提高性能dom,this.handleResize);},beforeDestroy(){constdom=this.$refs.col.$el;this.observer.removeListener(dom,this.handleResize);}};</script>
vue-resize-observer
如上所述的3种方法,或多或少都需要记忆一些语法
Q:Vue中,为什么不可以是一个自定义指令呢?
A:主角往往在最后出现,使用 vue-resize-observer 即可
注意:已支持Vue 3.x
示例
安装,在入口文件中引用:
importVueResizeObserverfrom"vue-resize-observer";Vue.use(VueResizeObserver);
ResizeObserver.observe(target,options)0
ResizeObserver.observe(target,options)1
什么时候触发执行handleResize?
初始化不会执行一次
文档视窗改变大小会执行
元素发现尺寸改变(非2导致)会执行
链接传送门
如何优雅监听容器高度变化
Last but not least
如有不妥,请多指教呀~