上篇内容说到,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!'
  }
})

自定义指令也支持动态参数