上篇内容说到,iframe嵌入其他项目页面,iframe实现自适应高度需要监听div页面高度的变化
使用到了局部自定义指定
directives: { // 使用局部注册指令的方式
resize: { // 指令的名称
// bind为自定义指令的钩子函数,只调用一次,指令第一次绑定到元素时调用
bind (el, binding) { // el为绑定的元素,binding为绑定给指令的对象,binding.value为指令的绑定值,例如:v-resize="resize",则binding.value为resize
let width = ''; let height = ''
function isReize () {
// 拿到el绑定元素的style样式
const style = document.defaultView.getComputedStyle(el)
// 判断当前的高度宽度是否发生了改变,如果改变了去调用binding.value绑定的函数也就是methods中的resize()方法,如果没有改变则不调用函数
if (width !== style.width || height !== style.height) {
binding.value() // 关键
}
width = style.width
height = style.height
}
// 每300毫秒调用一次isReize()方法,保证能随时监听el的高度宽度变化
el.__vueSetInterval__ = setInterval(isReize, 300)
},
// unbind也是自定义指令的钩子函数,只调用一次,指令与元素解绑时调用。当解绑时取消掉定时器,避免性能浪费
unbind (el) {
clearInterval(el.__vueSetInterval__)
}
}
},
methods: {
// 自定义指令的方法
resize () {
var hashH = document.documentElement.scrollHeight // 获取自身高度
// 获取最外层div的高度
var heightId = document.getElementById('iframe').scrollHeight
console.log(hashH, 'hashH', heightId)
// 全局下的parent其实是父页面的对象,所以调用postMessage()调用的也就是父级页面的方法,
window.parent.postMessage([hashH, heightId], '*')
},
}
// 在子页面最外层绑定自定义指令v-resize
<template>
<div id="iframe" v-resize="resize">
xxxxxxxx
</div>
</template>
自定义指令
全局注册
上文中是局部注册,自定义指令也可以全局注册,全局注册之后,可以在项目中任意地方使用
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
钩子函数
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
钩子函数的参数
el:自定义指令绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' + // demo
'value: ' + s(binding.value) + '<br>' + // hello (注意)
'expression: ' + s(binding.expression) + '<br>' + // message
'argument: ' + s(binding.arg) + '<br>' + // foo
'modifiers: ' + s(binding.modifiers) + '<br>' // {'a':true, 'b': true}
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
自定义指令也支持动态参数