Vue中如何实现自定义指令?

除了内置指令(如v-modelv-show),Vue允许你注册自己的自定义指令。它们主要用于需要对底层DOM进行直接操作的场景,例如输入框自动聚焦、按钮权限控制、图片懒加载或集成第三方DOM库。

注册自定义指令

你可以全局注册或局部注册一个指令。一个指令定义对象提供了一些可选的钩子函数,在指令绑定到元素的不同生命周期触发。

// 全局注册
const app = createApp({});
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});

// 局部注册(在组件内)
export default {
  directives: {
    focus: {
      mounted(el) {
        el.focus();
      }
    }
  }
}

注册后,你就可以在模板中使用v-focus指令了。

<input v-focus />

指令的钩子函数

一个指令定义对象可以包含以下钩子(Vue 3生命周期已重命名):

  • created:在绑定元素的attribute或事件监听器被应用之前调用。
  • beforeMount:在元素被插入到DOM之前调用。
  • mounted:绑定元素被插入到父节点时调用(最常用)。
  • beforeUpdate:在包含组件的VNode更新之前调用。
  • updated:在包含组件的VNode及其子组件的VNode更新后调用。
  • beforeUnmount:在绑定元素被卸载之前调用。
  • unmounted:绑定元素被卸载时调用。

这些钩子函数接收相同的参数:el(指令绑定的元素)、binding(一个包含指令信息的对象)、vnodeprevNode

深入binding对象

binding对象提供了指令的详细信息,是你编写灵活指令的关键。

directives: {
  demo: {
    mounted(el, binding) {
      console.log(binding.value);    // 指令的绑定值,例如 v-demo="1 + 1" 中的 2
      console.log(binding.oldValue); // 之前的值,仅在 beforeUpdate 和 updated 中可用
      console.log(binding.arg);      // 指令的参数,例如 v-demo:foo 中的 "foo"
      console.log(binding.modifiers);// 一个包含修饰符的对象,例如 v-demo.foo.bar 中的 { foo: true, bar: true }
      console.log(binding.instance); // 使用该指令的组件实例
    }
  }
}

实践示例:权限控制指令

一个常见的场景是根据用户角色控制按钮是否显示。

// 全局注册一个权限指令
app.directive('permission', {
  beforeMount(el, binding) {
    const { value } = binding; // 期望的权限角色,如 'admin'
    const userRole = getUserRole(); // 获取当前用户角色
    if (value && value !== userRole) {
      el.parentNode && el.parentNode.removeChild(el); // 无权限则移除元素
    }
  }
});
<button v-permission="'admin'">仅管理员可见</button>

在组合式API中简化

在Vue 3的组合式API中,你可以通过以v开头的驼峰式变量来创建自定义指令,这在<script setup>中尤为简洁。

<script setup>
const vFocus = {
  mounted(el) {
    el.focus();
  }
};
</script>
<template>
  <input v-focus />
</template>

自定义指令为你提供了直接操作DOM的通道,但应谨慎使用,因为Vue的理念是数据驱动。当常规的数据绑定和组件无法简洁地完成任务时(例如集成一个非Vue的日期选择器库),自定义指令就是一个得力的工具。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容