跳至内容

自定义指令
断裂

概述

指令的钩子函数已重命名,以更好地与组件生命周期保持一致。

此外,expression 字符串不再作为 binding 对象的一部分传递。

2.x 语法

在 Vue 2 中,自定义指令是通过使用下面列出的钩子来创建的,这些钩子用于定位元素的生命周期,所有这些钩子都是可选的

  • bind - 指令绑定到元素后调用一次。仅调用一次。
  • inserted - 元素插入父 DOM 后调用一次。
  • update - 当元素更新时调用此钩子,但子元素尚未更新。
  • componentUpdated - 当组件和子元素更新后调用此钩子。
  • unbind - 指令移除后调用此钩子。也仅调用一次。

以下是一个示例

html
<p v-highlight="'yellow'">Highlight this text bright yellow</p>
js
Vue.directive('highlight', {
  bind(el, binding, vnode) {
    el.style.background = binding.value
  }
})

在这里,在此元素的初始设置中,指令通过传入一个值来绑定一个样式,该值可以通过应用程序更新为不同的值。

3.x 语法

然而,在 Vue 3 中,我们为自定义指令创建了一个更具凝聚力的 API。如您所见,它们与我们的组件生命周期方法大不相同,即使我们正在挂钩到类似的事件。我们现在将它们统一如下

  • created - 新的!这在元素的属性或事件监听器应用之前调用。
  • bind → beforeMount
  • inserted → mounted
  • beforeUpdate: 新的!这在元素本身更新之前调用,就像组件生命周期钩子一样。
  • update → 已移除!与 updated 有太多相似之处,因此这是多余的。请改用 updated
  • componentUpdated → updated
  • beforeUnmount: 新的!类似于组件生命周期钩子,这将在元素卸载之前调用。
  • unbind -> unmounted

最终的 API 如下所示

js
const MyDirective = {
  created(el, binding, vnode, prevVnode) {}, // new
  beforeMount() {},
  mounted() {},
  beforeUpdate() {}, // new
  updated() {},
  beforeUnmount() {}, // new
  unmounted() {}
}

生成的 API 可以像这样使用,反映了前面的示例

html
<p v-highlight="'yellow'">Highlight this text bright yellow</p>
js
const app = Vue.createApp({})

app.directive('highlight', {
  beforeMount(el, binding, vnode) {
    el.style.background = binding.value
  }
})

现在,自定义指令生命周期钩子与组件本身的钩子相匹配,因此它们更容易理解和记忆!

边缘情况:访问组件实例

通常建议将指令保持独立于它们所使用的组件实例。从自定义指令中访问实例通常表明指令本身应该是一个组件。但是,在某些情况下,这实际上是有意义的。

在 Vue 2 中,必须通过 vnode 参数访问组件实例

js
bind(el, binding, vnode) {
  const vm = vnode.context
}

在 Vue 3 中,实例现在是 binding 的一部分

js
mounted(el, binding, vnode) {
  const vm = binding.instance
}

警告

使用 片段 支持,组件可能具有多个根节点。当应用于多根组件时,自定义指令将被忽略,并且会记录警告。

迁移策略

迁移构建标志:CUSTOM_DIR