一、什么是自定义指令
我们已经熟悉Vue 内置的一系列指令 ,比如 v-model , v-show , v-if , v-for 等等,自定义指令从命名上看主要区别于Vue 自带的内置指令,我们可以创建自己想要的指令,使用必须以v- 为前缀
二、指令的分类
- 局部指令:组件中通过
directives 选项实现,只能在当前组件中使用 - 全局指令:应用实例的
directive 方法,可以在任意组件中被使用(所有内置指令都为全局指令)
三、指令的作用
四、指令的钩子
指令的钩子和组件的生命周期很像,只是没有beforeCreate
const myDirective = {
created(el, binding, vnode, prevVnode) {
},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeUnmount() {},
unmounted() {}
}
五、钩子参数
指令的钩子会传递以下几种参数:
-
el :指令绑定到的元素。这可以用于直接操作 DOM。 -
binding :一个对象,包含以下 property:
value :传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。oldValue :之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。arg :传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。modifiers :一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。instance :使用该指令的组件实例。dir :指令的定义对象。 -
vnode :代表绑定元素的底层 VNode。 -
prevNode :之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。
六、指令的使用
简单需求: 当某个元素挂载完成后可以自定获取焦点
默认的实现方式,假如有多个地方需要使用时,这种实现方式的代码会显得繁杂冗余
<template>
<div>
<input type="text" ref="input" />
</div>
</template>
<script>
import { ref, onMounted } from "vue";
export default {
setup () {
const input = ref(null);
onMounted(() => {
input.value.focus();
})
return {
input
}
}
}
</script>
<style scoped>
</style>
使用自定义指令实现
<template>
<input type="text" v-focus />
</template>
<script setup>
const vFocus = {
mounted: (el) => el.focus()
}
</script>
注:在<script setup> 中,任何以 v 开头的驼峰式命名的变量都可以被用作一个自定义指令,vFocus 即可以在模板中以 v-focus 的形式使用
如果不使用 <script setup> ,自定义指令可以通过 directives 选项注册
<template>
<input type="text" v-focus />
</template>
<script>
export default {
setup() {
},
directives: {
focus: {
mounted: (el) => el.focus()
}
}
}
</script>
也可以全局注册该指令,这样所有组件都可以使用v-focus
const app = createApp({})
app.directive('focus', {
mounted: (el) => el.focus()
})
指令的参数和修饰符
假如我们使用这样一个指令v-example
<div v-example:params.lazy="someValue"></div>
此时指令钩子函数的binding 参数会是一个这样的对象:
{
arg: 'params',
modifiers: { lazy: true },
value: ,
oldValue:
}
也就是说指令: 后面跟着的是指令的参数,. 后面跟着的是指令的修饰符
简单示例一:
背景高亮
<template>
<div>
<div v-highlight>默认的高亮颜色</div>
<div v-highlight="{ bgColor: 'red', color: 'yellow' }">这是一个简单的例子</div>
</div>
</template>
<script>
export default {
setup() {
},
directives: {
highlight: {
mounted(el, binding) {
console.log('binding', binding)
const color = binding.value && binding.value.color ? binding.value.color : '#fff'
const bgColor = binding.value && binding.value.bgColor ? binding.value.bgColor : 'blue'
el.style.color = color
el.style.backgroundColor = bgColor
}
}
}
}
</script>
简单示例二:
<template>
<div>
<div v-letter:uppercase>hello world</div>
</div>
</template>
<script>
export default {
setup() {
},
directives: {
letter: {
mounted(el, binding) {
const text = el.innerHTML
if (binding.arg === 'uppercase') {
el.innerHTML = text.toUpperCase()
} else if (binding.arg === 'lowercase') {
el.innerHTML = text.toLowerCase()
} else {
el.innerHTML = text.split('')
}
}
}
}
}
</script>
|