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