创建文件:/src/directive/winresize/winresize.js
定义directive事件,创建侦听事件返回元素宽高
// 实时监测窗口变化,返回当前元素的宽度和高度
// 调用方式 v-winresize="自定义接收函数"
const winresize = {
bind: (el, binding, vnode) => {
// bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
function documentHandler(e) {
if (binding.expression) {
//返回当前元素的宽度和高度
binding.value(el.offsetWidth, el.offsetHeight)
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueWindowsResize__ = documentHandler
window.addEventListener('resize', documentHandler)
},
inserted: () => {
// inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
},
update: () => {
// update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
},
componentUpdated: () => {
// componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
},
unbind: (el, binding) => {
// unbind: 只调用一次, 指令与元素解绑时调用。
window.removeEventListener('onresize', el.__vueWindowsResize__)
delete el.__vueWindowsResize__
}
}
export default winresize
问题点:这种directive创建的侦听事件是全局定义的,如果多个元素同时绑定的时候,会被同步执行,特别注意在侦听点击事件的时候,任意一个被点击,其它的元素也会响应点击事件,这里需要在定义的侦听事件里做如下处理:判断点击的元素是否是本身,不是本身,则返回
function documentHandler(e) {
// 这里判断点击的元素是否是本身,不是本身,则返回
if (!el.contains(e.target)) {
return false
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
binding.value(e)
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler
document.addEventListener('mouseup', el.__vueClickOutside__)
创建文件:/src/directive/winresize/index.js
绑定全局directive,通用的定义方式,方便后期扩展功能:
import Vue from 'vue'
// 加载文件
import winresize from './winresize'
// 绑定directive
Vue.directive('winresize', winresize)
编辑文件:/src/main.js
加入下面代码就完成了全局的定义,任意页面都可以对元素设置 v-winresize=""
import '@/directive/winresize'
实际调用代码如下:
<template>
<div ref="mapwin" style="width: 100%; height: 100%;" v-winresize="setmapmainsize">
<div style="width: 200px; height: 100%;">固定宽度的部分</div>
<div :style="styledata">需要占满剩余空间的部分</div>
</div>
</template>
<script>
export default {
name: 'map',
data() {
return {
winWidth: 0,
winHeight: 0,
styledata: {width:'', height: '100%'}
}
},
methods: {
setmapmainsize(_w, _h) {
this.winWidth = _w
this.winHeight = _h
this.styledata = {
width: this.winWidth + 'px',
eight: '100%'
}
}
},
mounted: function () {
// mounted 挂载结束状态
// 设置元素的宽度和高度,一定要在挂载完成后来执行
this.setmapmainsize(this.$refs.mapwin.offsetWidth, this.$refs.mapwin.offsetHeight)
}
}
</script>