Vue3$View-CustomDirectives

36 阅读2分钟

Vue3$View-CustomDirectives

0. Custom Directives in Big Picture

指令是用来操作 DOM 的。Vue 提供的内置指令可以完成大部分功能,但有时我们也需要自定义指令。

一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。

<script setup>
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

<template>
  <input v-focus />
</template>
const app = createApp({})

// 全局 v-focus
app.directive('focus', {
  /* ... */
})

1. 组件的定义

Directive Hooks

const myDirective = {
  // called before bound element's attributes
  // or event listeners are applied
  created(el, binding, vnode, prevVnode) {
    // see below for details on arguments
  },
  // called right before the element is inserted into the DOM.
  beforeMount(el, binding, vnode, prevVnode) {},
  // called when the bound element's parent component
  // and all its children are mounted.
  mounted(el, binding, vnode, prevVnode) {},
  // called before the parent component is updated
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // called after the parent component and
  // all of its children have updated
  updated(el, binding, vnode, prevVnode) {},
  // called before the parent component is unmounted
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // called when the parent component is unmounted
  unmounted(el, binding, vnode, prevVnode) {}
}

参数

  • el:指令绑定到的元素。(可读可写)
  • binding:对象,包含以下属性
    • value:传递给指令的值。
    • oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。
    • arg:传递给指令的参数
    • modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }
    • instance:使用该指令的组件实例。
    • dir:指令的定义对象。
  • vnode:代表绑定元素的底层 VNode。
  • prevVnode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。

函数简写

mountedupdated

app.directive('color', (el, binding) => {
  // this will be called for both `mounted` and `updated`
  el.style.color = binding.value
})

2. 使用

在组件上使用

不推荐。只能用在单根元素组件上。

防止重复提交

// 1. 设置 v-throttle 自定义指令
app.directive('throttle', {
  mounted(el, binding) {
    let throttleTime = binding.value; // 节流时间
    if (!throttleTime) {
      throttleTime = 2000;
    }
    let cbFun;
    el.addEventListener('click', event => {
    // 第一次点击:执行&设置时间
      if (!cbFun) {
        cbFun = setTimeout(() => {
          cbFun = null;
        }, throttleTime);
        // 时间内点击:不允许
      } else {
        event && event.stopImmediatePropagation();
      }
    }, true);
  },
});
// 2. 使用
<button @click="sayHello" v-throttle>提交</button>

Links

VueCumstomDirectives

Vue面试系列自定义指令