vue3.x学习笔记之自定义指令

  • • vue3 自定义指令

      • • Vue3 自定义指令的基本结构

      • • Vue3 自定义指令简单的示例:

      • • vue3 组件中自定义指令

      • • vue3 组件 setup 语法糖 中 自定义指令

    • • 扩展:vue2 中如何自定义指令

      • • 全局指令

      • • 局部指令

vue3 自定义指令

Vue3 中自定义指令允许开发者扩展 Vue 的 HTML 属性功能,创建自定义的行为。

Vue3 对自定义指令的 API 进行了更新,与 Vue2 相比更加灵活和可组合。

Vue3 自定义指令的基本结构

在 Vue3 中定义自定义指令的基本结构如下:

// 全局注册一个自定义指令
const myDirective = {
  // 指令被绑定到元素时调用,仅调用一次
  created: (el, binding, vnode) => {},
  // 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
  mounted: (el, binding, vnode) => {},
  // 指令所在组件的 VNode 及其子 VNode 更新时调用
  updated: (el, binding, vnode) => {},
  // 指令所在组件的 VNode 及其子 VNode 销毁时调用
  beforeUnmount: (el, binding, vnode) => {},
  // 指令所在组件的 VNode 及其子 VNode 完全卸载时调用
  unmounted: (el, binding, vnode) => {},

  // 钩子函数可以接收三个参数:
  // el:指令所绑定的元素
  // binding:一个对象,包含以下属性:
  //   - name:指令名
  //   - value:传递给指令的值(例如:v-my-directive="value" 中的 value)
  //   - oldValue:上一个值,在 updated 和 beforeUpdate 钩子中可用
  //   - arg:传给指令的参数(例如:v-my-directive:foo 中的 "foo")
  //   - modifiers:一个对象,包含了修饰符列表(如 .prevent、.stop 等)
  // vnode:Vue 编译生成的虚拟节点
  // oldVnode:上一个虚拟节点,在 updated 和 beforeUpdate 钩子中可用
}

// 全局注册
app.directive('my-directive', myDirective)

// 或者在单个组件内局部注册
export default {
  directives: {
    'my-directive': {
      // 在此处定义指令逻辑
      mounted(el, binding, vnode) {
        // 示例逻辑:当元素挂载时,获取焦点
        el.focus()
      },
    },
  },
}

在模板中使用自定义指令的语法是 v-my-directive,如果需要传递参数,则可以写作 v-my-directive:arg,同时也可以添加修饰符,例如 v-my-directive.modifier1.modifier2

Vue3 中自定义指令的设计理念鼓励通过组合API(如 refcomputed 和 watch)来实现更复杂的功能,而非过度依赖指令机制。

不过对于一些特定场景下,自定义指令仍然是一种简洁且强大的工具。

更多详细内容,请微信搜索“前端爱好者, 戳我 查看 。

Vue3 自定义指令简单的示例:

在Vue3中自定义指令的步骤如下,并给出一个简单的示例:

假设我们要创建一个自定义指令,该指令用于当元素挂载到页面时自动聚焦到输入框。

首先,定义一个自定义指令对象,其中包含必要的生命周期钩子函数:

// 自定义指令逻辑
const focusDirective = {
  mounted(el, binding) {
    // el 是指令绑定到的 DOM 元素
    // binding 是一个对象,包含了如 value、arg、modifiers 等信息
    if (binding.value && typeof binding.value === 'string') {
      // 如果传入了参数,则根据参数决定是否聚焦(此处简单地判断参数为 "auto" 时聚焦)
      if (binding.value === 'auto') {
        el.focus();
      }
    } else {
      // 若无参数或参数不为 "auto",默认进行聚焦
      el.focus();
    }
  },
};

// 全局注册自定义指令
const app = createApp(App);
app.directive('focus', focusDirective);

// 或者在某个组件内部局部注册
export default {
  directives: {
    focus: focusDirective,
  },
};

然后,在模板中使用这个自定义指令:

<input type="text" v-focus />
<!-- 或带有参数 -->
<input type="text" v-focus:auto />

在这个例子中,v-focus 指令会在相应输入框挂载到DOM后立即获取焦点。

如果指定了参数 :auto 并且其值等于 'auto',则会执行聚焦操作;否则,无论是否有参数,都会默认聚焦。当然,实际应用中可以根据需求定制更复杂的逻辑。

vue3 组件中自定义指令

在Vue3组件中自定义指令,可以局部注册到该组件内部。

以下是一个在单个组件内创建和使用自定义指令的示例:

// 假设这是你的某个Vue组件
import { createApp, ref } from 'vue';

// 定义一个局部指令逻辑
const focusDirective = {
  mounted(el) {
    el.focus();
  },
};

export default {
  // 指令注册到组件的 directives 对象上
  directives: {
    focus: focusDirective,
  },

  setup() {
    const inputText = ref('');

    return {
      inputText,
    };
  },

  template`
    <div>
      <!-- 在本组件模板内使用自定义指令 -->
      <input type="text" v-focus :value="inputText" @input="event => (inputText.value = event.target.value)" />
    </div>
  `
,
};

// 创建应用并挂载根组件
const app = createApp(App);
app.mount('#app');

在这个例子中,我们创建了一个名为 focus 的局部指令,它会在元素被挂载后立即调用 el.focus() 方法来聚焦对应的DOM元素。然后我们在组件内部的 <input> 标签上通过 v-focus 使用这个自定义指令,这样当输入框渲染时会自动获取焦点。

在实际项目中,你可能还需要根据需求处理更多复杂的指令逻辑,比如传递参数、响应式更新等。

vue3 组件 setup 语法糖 中 自定义指令

在Vue3的<script setup>语法糖中,自定义指令仍然不会直接在setup函数内部定义,而是按照Vue3的传统方式在组件外部或者全局进行注册。

这是因为自定义指令是一个全局或局部注册的机制,并非组件实例的功能。

然而,在使用<script setup>编写组件时,你可以结合Composition API来创建指令逻辑,并在同一个文件内局部注册这个指令,然后在模板中应用它。

以下是如何在一个单文件组件(SFC)内局部注册一个自定义指令:

<template>
  <input type="text" v-focus />
</template>

<script setup lang="ts">
import { onMounted, ref, directive } from 'vue';

// 定义指令逻辑
const focusDirective = {
  mounted(el) {
    // 使用onMounted钩子确保DOM已挂载
    onMounted(() => {
      el.focus();
    });
  },
};

// 局部注册指令到当前组件作用域
defineComponent({
  directives: {
    focus: focusDirective,
  },
});
</script>

这里需要注意的是,在<script setup>语法糖中并没有直接提供对directives选项的暴露和设置。

因此,需要借助defineComponent函数来注册指令,但这并不是标准做法,因为<script setup>的目的之一是减少此类手动操作。

实际项目中,自定义指令通常会独立出来并在全局或者模块级别进行注册,而不是在每个使用它的组件内都重新注册一次。

例如:

// directives/focus.js
export const focus = {
  mounted(el) {
    el.focus();
  },
};

// 在main.js或者其他合适的地方全局注册
import { createApp } from 'vue';
import { focus } from './directives/focus';

const app = createApp(App);
app.directive('focus', focus);

app.mount('#app');

然后在任何组件中,包括使用<script setup>的组件,都可以直接使用v-focus指令而无需额外配置。

扩展:vue2 中如何自定义指令

在Vue2中自定义指令可以分为全局指令和局部指令两种方式。

全局指令

全局指令可以在整个Vue应用范围内生效,你可以在任何组件中使用它。创建全局指令的步骤如下:

// 在你的Vue应用初始化文件或单独的插件文件中
Vue.directive('my-directive', {
  // 钩子函数
  bindfunction (el, binding, vnode) { // 绑定元素时调用
    // 'el' 是绑定指令的DOM元素
    // 'binding' 是一个对象,包含:
    //   - name: 指令名(不带v-前缀)
    //   - value: 指令的绑定值
    //   - oldValue: 上一个绑定值(仅在update钩子中可用)
    //   - expression: 指令表达式的字符串形式
    //   - arg: 传递给指令的参数(如果有)
    //   - modifiers: 修饰符对象
    // 'vnode' 是虚拟节点

    // 示例:为元素添加一个class
    el.classList.add(binding.value);
  },
  
  insertedfunction (el, binding, vnode) { // 插入DOM时调用 }
  
  updatefunction (el, binding, vnode) { // 当绑定值变化时调用 }
  
  componentUpdatedfunction (el, binding, vnode) { // 元素更新后及它的子元素也完成更新后调用 }
  
  unbindfunction (el, binding, vnode) { // 指令与元素解绑时调用 }
});

局部指令

局部指令是在单个组件内部定义并使用的,通过组件的 directives 选项来实现:

Vue.component('MyComponent', {
  directives: {
    'my-directive': {
      bindfunction (el, binding, vnode) {...},
      // 其他钩子函数...
    }
  },
  template`
    <div v-my-directive="someValue">...</div>
  `
,
  ...
});

在上述代码中,my-directive 就是我们自定义的指令名称,它会在相应钩子函数执行时对DOM元素进行操作。根据需要,你可以选择在适当的钩子函数内编写逻辑,比如响应数据变化、操作DOM属性或样式等。

原文始发于微信公众号(前端爱好者):vue3.x学习笔记之自定义指令

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/267270.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!