在某些业务场景中,我们需要监听元素的尺寸变化处理一些逻辑问题。但是没有像window的resize方法一样的方法直接能够监听到DOM尺寸的变化,所以只能采用曲线救国的方式。
实现思想
- 动态创建 Object标签,追加到容器中,宽高继承容器100%;
- load完成后获取 Object中的contentDocument,通过defaultView添加resize事件监听;
实现过程
- 实现domResize.js
const domResize = {
bind(el, binding) {
const { value: handleFn } = binding //value即是自定义指定绑定的值,可以使函数或者是其他属性
let obj = document.createElement('object');
obj.style.display = 'block'
obj.style.position = 'absolute'
obj.style.top = '0px'
obj.style.left = '0px'
obj.style.width = '100%'
obj.style.height = '100%'
obj.style.border = 'none'
obj.style.padding = '0'
obj.style.margin = '0'
obj.style.opacity = '0'
obj.style.zIndex = '-1000'
obj.style.pointerEvents = 'none'
obj.type = 'text/html'
obj.tabindex = "-1"
obj.type = "text/html"
obj.data = "about:blank"
obj['aria-hidden'] = "true"
el.appendChild(obj);
obj.onload = () => {
obj.contentDocument.defaultView.addEventListener('resize', () => {
handleFn()
// 也可直接将width/height值暴露出去
})
}
}
}
export default domResize
- 实现vue中自定义组件的目录index.js
import domResize from './domResize'
const directives = {
domResize
}
export default {
install(Vue) {
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key])
})
}
}
- main.js中统一注册自定义指令
import Vue from 'vue'
import App from './App.vue'
import directives from '@/directives/index.js'
Vue.use(directives)
new Vue({
render: h => h(App),
}).$mount('#app')
- 页面使用
<template>
<div class="dom" v-dom-resize="resizeFn">
</div>
</template>
<script>
import {cloneDeep} from 'yan-utils/lib/object'
export default {
methods:{
resizeFn(){
// 执行一些尺寸变化的逻辑操作
}
}
}
</script>
<style lang="less" scoped>
.dom{
position: relative;
width: 100%;
height:100%;
}
</style>
总结
实现监听元素尺寸变化的方法有很多,还可以通过创建iframe标签,或者设置定时器比较元素尺寸的方法,具体就不详细展开。