一、directive自定义指令
vue中有v-if,v-for等一系列的方便快捷的指令。我们也可以自定义指令.
自定义指令可以提取出原生DOM操作的逻辑。所以指令的应用范围主要表现在,当一些操作涉及到 DOM 底层时,而且操作逻辑可能用于多处地方,就适合用指令来封装这些逻辑。
vue3指令的钩子函数
- created元素初始化的时候
- beforeMount指令绑定到元素后调用 只调用一次
- mounted元素插入父级dom调用
- beforeUpdate元素被更新之前调用
- update这个周期方法被移除改用updated
- beforeUnmount在元素被移除前调用
- unmounted指令被移除后调用,只调用一次
指令的命名方式
以vNameOfDirective的形式来命名本地自定义指令,以使得它们可以直接在模板中使用。
<template>
<div>
<button @click="flag=!flag">切换</button>
<!-- 给自定义指令传参数、修饰符、值 -->
<!-- 加v-if用来触发beforeUnmount和unmounted -->
<!-- <A v-if="flag" v-move:aaa.kangyun="{background: 'red'}"></A> -->
<!-- 值中的数据变化就会触发beforeupdate, updated -->
<A v-move:aaa.kangyun="{background: 'red', flag: flag}"></A>
</div>
</template>
<script setup lang="ts">
import A from './components/A.vue'
import { ref, Directive, DirectiveBinding } from 'vue'
let flag = ref<boolean>(true)
type Dir = {
background: string
}
const vMove: Directive = {
created(...args:Array<any>){
console.log(args)
console.log('created')
},
// dir相当于我们传过来的参数
// type Dir方便我们推导出来background
beforeMount(el: HTMLElement, dir: DirectiveBinding<Dir>){
console.log('beforeMount')
console.log(dir.value.background)
el.style.background = dir.value.background
},
// 自定义指令传过来的数据在任何一个钩子函数中都可以接收到
mounted(){
console.log('mounted')
},
beforeUpdate(){
console.log('beforeUpdate')
},
updated(){
console.log('updated')
},
beforeUnmount(){
console.log('beforeUnmount')
},
unmounted(){
console.log('unmounted')
}
}
</script>
<style scoped>
</style>
二、函数简写
在mounted和updated时触发相同的行为,而不关心其他的勾子函数,可以通过这个函数模式实现
封装一个按钮级别的鉴权指令
<template>
<div>
<button v-is-show="'user-edit'">添加</button>
<button v-is-show="'user-create'">编辑</button>
<button v-is-show="'user-delete'">删除</button>
</div>
</template>
<script setup lang="ts">
import type { Directive } from "vue";
// 模拟从后台获取到用户的ID并存入localStorage中
localStorage.setItem("userId", "yhdlj");
// 从后台获取用户的ID及相关模组的权限
const permission = [
"yhdlj-user-edit",
// 如果没有返回相关的权限按钮将不会显示
"yhdlj-user-create",
"yhdlj-user-delete",
];
const userId = localStorage.getItem("userId");
const vIsShow: Directive<HTMLElement, string> = (el, dir) => {
if (!permission.includes(`${userId}-${dir.value}`)) {
el.style.display = "none";
}
};
</script>
<style scoped></style>