返回介绍

五、自定义指令

发布于 2024-04-04 21:33:24 字数 3791 浏览 0 评论 0 收藏 0

Vue 2.x

在 Vue 2 中,自定义指令通过使用下列钩子来创建,以对齐元素的生命周期,它们都是可选的:

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

边界情况:访问组件实例

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

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

Vue 3.x

在 Vue 3 中,统一生命周期

  • created - 新增!在元素的 attribute事件监听器被应用之前调用。
  • bind → beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用
  • inserted → mounted:在绑定元素的父组件被挂载前调用
  • beforeUpdate:新增!在元素本身被更新之前调用,与组件的生命周期钩子十分相似。
  • update → 移除!该钩子与 updated 有太多相似之处,因此它是多余的。改用 updated
  • componentUpdated → updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用
  • beforeUnmount:新增!与组件的生命周期钩子类似,它将在元素被卸载之前调用(在卸载绑定元素的父组件之前调用)。
  • unbind -> unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次。

最终的 API 如下:

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

示例:

<p v-highlight="'yellow'">以亮黄色高亮显示此文本</p>
const app = Vue.createApp({})

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

setup 中定义局部指令

// 注册一个局部的自定义指令,需要以小写 v 开头
const vFocus = {
	mounted(el) {
    // 获取 input,并调用其 focus() 方法
    el.focus()
  }
}

边界情况:访问组件实例

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

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

在组件中使用

非 prop 的 attribute 类似,当在组件中使用时,自定义指令总是会被应用在组件的根节点上。

<my-component v-demo="test"></my-component>
app.component('my-component', {
  template: `
    <div> // v-demo 指令将会被应用在这里
      <span>My component content</span>
    </div>
  `
})

和 attribute 不同,指令不会通过 v-bind="$attrs" 被传入另一个元素

有了 片段 的支持,组件可能会有多个根节点。当被应用于多根组件时,自定义指令将被忽略,并将抛出警告。

函数简写

mountedupdated 时触发相同行为,而不关心其他的钩子函数。那么你可以通过将这个回调函数传递给指令来实现:

app.directive('pin', (el, binding) => {
  el.style.position = 'fixed'
  const s = binding.arg || 'top'
  el.style[s] = binding.value + 'px'
})

对象字面量

如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法的 JavaScript 表达式。

<div v-demo="{ color: 'white', text: 'hello!' }"></div>
app.directive('demo', (el, binding) => {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text) // => "hello!"
})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文