[译] Vue 3 迁移策略 —— 自定义指令(破坏性改动)

1,526 阅读1分钟

需要调研 vue 2 到 vue 3 的迁移方案,来做内部分享。

我看网上貌似目前只有一人翻译了,翻译了前几章。

但是我着急用,只能自己翻了。译者四级没过,全靠有道和谷歌了。

vue 3 官方文档原文—— custom directives

自定义指令

概览

以下是更改内容的快速摘要:

  • API已重命名以更好地与组件生命周期保持一致
  • 自定义指令将由子组件通过 v-bind="$attrs"

2.x 语法

Vue 2 中,可以使用下列生命周期钩子函数来创建自定义指令,所有这些都是可选的:

  • bind - 指令第一次绑定到元素时调用。仅调用一次。
  • inserted - 当元素插入复 DOM 时调用。
  • update - 当元素更新,子元素尚未更新时调用。
  • componentUpdated - 当组件以及子组件更新后调用。
  • unbind - 当指令被删除时调用,也是只调用一次

示例如下:

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

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

3.x 语法

但是,在 Vue 3 中,我们为自定义指令创建了更加紧密的API。 如您所见,即使我们觉得它们都是类似的事件,但它们与我们组件的生命周期方法却大不相同。 现在,我们将它们统一为:

  • bind -> beforeMount
  • inserted -> mounted
  • beforeUpdate: new! 在元素本身更新之前调用,就像组件生命周期的钩子函数一样。
  • update: removed! 与 updated 有太多相似之处,因此这是多余的。 请改用 updated
  • componentUpdated -> updated
  • beforeUnmount: new! 与组件的生命周期钩子函数类似,会在元素卸载之前立即调用。
  • unbind -> unmounted

最终的 API 如下:

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

可以像这样使用所得的 API,对照先前的示例:

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

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

实施细节

在 Vue 3 中,我们现在支持多个片段,允许每个组件返回多个 DOM 节点。您可以想象这对于像具有多个 li 的组件或 table 的子元素之类的东西有多方便:

<template>
  <li>Hello</li>
  <li>Vue</li>
  <li>Devs!</li>
</template>

由于片段功能如此灵活,我们可能会遇到一个自定义指令的问题:指令可以对应多个根节点。

因此,自定义指令现在已包含在虚拟 DOM 节点数据中。当在组件上使用自定义指令时,钩子函数将作为无关的道具向下传递到组件,并最终出现在 this.$attrs 中。

这也意味着可以像这样在模板中直接挂载到元素的生命周期,当自定义指令过于深入时,这将很方便:

<div @vnodeMounted="myHook" />

这与属性下降行为是一致的,因此,当子组件在内部元素上使用 v-bind="$attrs" 时,它也会应用在其上使用的所有自定义指令。