vue3-自定义指令,一文让你熟用direactive

158 阅读2分钟

案例

对于自定义指令,我这里使用一个简单的案例来先说明:通过案例会更快入手

使用vue3的过程有一个需求,在按钮按下以及松开分别执行不同的事件。需要兼容移动端以及pc点击事件。即我们可以使用mousedown,mouseup移动端使用touchstart,touchend。如果使用常规写法,那就是判断移动端还是pc端,绑定不同事件。

可见下面的写法会比较累赘的,而且代码冗余

<template>
    <div v-if="utils.isPC()" @mousedown="handleStart" @mouseup="handleEnd">
        // do something
    </div>
    <div v-else @touchstart="handleStart" @touchend"="handleEnd">
        // do something
    </div>
</template>

使用自定义指令:局部使用

<template>
    <div v-kstart="hanldeStart" v-kend="handleEnd">
       // do something
    </div>
</template>

<script setup>
const handleStart = (e) => {
    console.log(e.tyoe)
}
</script>

<script>
// 区分终端事件
const ev = utils.isPc() ? ['mousedown', 'mouseup'] : ['touchstart', 'touchend']

export default {
directives: {
    kstart: {
      mounted (el, binding) {
        el.addEventListener(ev[0],(e) => {
          binding.value(e)
        })
      }
    },
    kend: {
      mounted (el, binding) {
        el.addEventListener(ev[1],(e) => {
          binding.value(e)
        })
      }
    }
  }
}
</script>

全局使用

在main.js中

const APP = createApp(App)
APP.directive('ksatr', {
    mounted (el, binding) {
        el.addEventListener(ev[0],(e) => {
            binding.value(e)
        })
    }
})

APP.use(Router).use(Store).mount('#app')  

vue3 自定义指令详细API解说

app.directive('my-directive', {
  // 指令具有一组生命周期钩子:
  // 在绑定元素的 attribute 或事件监听器被应用之前调用
  created() {},
  // 在绑定元素的父组件挂载之前调用
  beforeMount() {},
  // 在绑定元素的父组件挂载之后调用
  mounted(el, binding) {},
  // 在包含组件的 VNode 更新之前调用
  beforeUpdate() {},
  // 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
  updated() {},
  // 在绑定元素的父组件卸载之前调用
  beforeUnmount() {},
  // 在绑定元素的父组件卸载之后调用
  unmounted() {}
})

// 注册 (函数指令)
app.directive('my-directive', () => {
  // 这将被作为 `mounted` 和 `updated` 调用
})

// getter, 如果已注册,则返回指令定义
const myDirective = app.directive('my-directive')

获取调用对象:el


<script>
export default {
    directives: {
        myDirective: {
            mouted (el, binding) {
                // el 为调用实例对象,即dom 
                console.log(el) // <div> do something </div>
            }
        }
    }
}
</script>

binding 对象

  • instance:使用指令的组件实例。
  • value:传递给指令的值。例如,在 v-my-directive="1 + 1" 中,该值为 2
  • oldValue:先前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否有更改都可用。
  • arg:传递给指令的参数(如果有的话)。例如在 v-my-directive:foo 中,arg 为 "foo"
  • modifiers:包含修饰符(如果有的话) 的对象。例如在 v-my-directive.foo.bar 中,修饰符对象为 {foo: true,bar: true}
  • dir:一个对象,在注册指令时作为参数传递。

instance

相当于获取到是这个组件的实例:举个例子 k-button.vue组件中

<template>
    <div v-kstart="handlestart"></div>
</template>

<script setup>
const props = defineProps({
  item: {
    default: () => ({}),
    type: Object
  },
  type: {
    default: ''
    type: [String, Number]
  }
})
</script>

<script>
export default {
    directives: {
        kstart: {
            mouted (el, binding) {
                console.log(binding.instance) // 打印如下图,就可以直接获取当前组件的实例
            }
        }
    }
}
</script>

image.png

value

相当于抛出给回调的参数

<template>
    <div v-kstart="handlestart"></div>
</template>

<script setup>
const handlestart = (resp) => {
   console.log(resp) // 1 接收到自定义返回的处理响应值
}
</script>

<script>
export default {
    directives: {
        kstart: {
            mouted (el, binding) {
                binding.value(1)
            }
        }
    }
}
</script>

oldValue

当传入的值改变了,oldValue就为前一次的值.

<template>
    <div v-ktest:msg="msg">{{ msg }}</div>
    <div @click="msg='k1'">点击改变msg</div>
</template>

<script>
export default {
    data () {
        return {
            msg: 'test'
        }
    },
    directives: {
        ktest: {
            updated (el, binding) {
                console.log(binding.oldValue) // test
            }
        }
    }
}
</script>

arg:传给指令的参数

<template>
    <div v-ktest:msg="msg">{{ msg }}</div>
</template>

<script>
export default {
    data () {
        return {
            msg: 'test'
        }
    },
    directives: {
        ktest: {
           mouted (el, binding) {
               console.log(binding.value.msg) // test
           }
        }
    }
}
</script>

参考文献:
VUE3-API