自定义指令:自定义指令就是自己创建一个指令,有时候vue提供的指令,不能满足我们的需求,刚好vue提供了允许我们自己注册自定义指令,所有我们就自己创建一个了指令,这个就是自定义指令。写法:v-指令名称。
创建自定义指令分别有全部注册 和 局部注册。通过创建好的自定义指令实现:
- 操作DOM:可以直接对 DOM 元素进行操作,比如修改样式、添加事件监听器
- 数据绑定:让数据和 DOM 元素实现双向绑定
- 表单校验:对表单进行验证,比如自定义输入框格式、校验规则等
- 代码复用:将一些常用的操作封装成指令,提到代码的复用性
- 按钮权限:根据不同的用户权限,显示不同的按钮 比如管理员具有增删改查,普通用户则只有查
同时还可以实现一些特殊的需求
全局自定义指令:Vue.directive(‘指令名’,{ inserted(el) { } })
局部自定义指令:directives:{ }
vue2和vue3的自定义指令的区别,它们基本使用方式和原理是一样的,只是它们携带的生命周期钩子函数有所改变,写法不同
vue2中的绑定的钩子函数
- bind - 绑定 指令绑定到元素后调用,且只调用一次,因为只会绑定一次
- inserted - 节点在插入的时候调用
- update - 在更新的时候调用
- componentUpdated - 在组件更新完成后调用
- unbind - 解绑的时候调用 也是只会调用一次
vue3中绑定的钩子函数
- bind - beforeMount
- inserted - mounted
- beforeUpdate - 新增 元素更新之前调用
- componentUpdated - updated
- beforeUnmount - 新增 在元素卸载之前调用
- unbind - unmounted
详情:
const myDirective = {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el, binding, vnode, prevVnode) {
// 下面会介绍各个参数的细节
},
// 在元素被插入到 DOM 前调用
beforeMount(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件更新前调用
beforeUpdate(el, binding, vnode, prevVnode) {},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载前调用
beforeUnmount(el, binding, vnode, prevVnode) {},
// 绑定元素的父组件卸载后调用
unmounted(el, binding, vnode, prevVnode) {}
}
钩子函数中的参数我们一般使用 el 和 binding
- el:指令绑定的元素,一般用来直接操作DOM
binding:一个对象,包含多个属性
- value: 元素绑定指令给传递的值。 如:v-指令名称='传递的值'
- oldValue: 之前的值。只在
beforeUpdate
和updated
中可以用。不管值是否更改,都可以使用 - arg:传递给指令的参数。如:v-指令名称:foor;参数就是 foor
- dir: 指令的定义对象
- instance: 使用该指令的组件实例
- modifiers:包含修饰符的对象。如:v-指令名称.foor.bar;修饰符对象就是
{foo:true,bar:true}
。
还有两个参数是:
vnode:代表绑定元素的底层 VNode。
prevNode:代表之前的渲染中指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用。
小案例:图片裂图
局部注册
<script>
import {ref} from "vue"
// 正常图片
const img = ref("https://pic3.zhimg.com/v2-d5605e12f258084b0f31c857892f5629_r.jpg?source=1940ef5c")
// 图片裂图
const errImg = ref("https://img.ixintu.com/download/jpg/20200811/384e01b995f6c72ff79a1f1c8a7a87ba_512_384.jpg!ys")
// 自定义图片裂图指令
const vImg = { // 必须是 v开头的驼峰式命名
mounted(el: any, bing: any) {
// console.log(111, el, bing);
el.onerror = function () {
console.log(111);
// 更改图片
el.src = bing.value
}
}
}
</script>
<template>
<!-- 图片裂图 -->
<img v-img="errImg" :src="img">
</template>
全局注册自定义指令在main.ts中
main.ts
app.directive("img", {
mounted: (el, binding) => {
console.log(666, el, binding);
// 监听错误信息
el.addEventListener('error', function () {
// 发送错误后 显示裂图
el.src = binding.value
})
}
})
Home.vue组件中
<scirpt lang="ts" setup>
import {ref} from "vue"
// 正常图片
const img = ref("https://pic3.zhimg.com/v2-d5605e12f258084b0f31c857892f5629_r.jpg?source=1940ef5c")
// 图片裂图
const errImg = ref("https://img.ixintu.com/download/jpg/20200811/384e01b995f6c72ff79a1f1c8a7a87ba_512_384.jpg!ys")
<template>
<!-- 图片裂图 -->
<img v-img="errImg" :src="img">
</template>
注意:在全局中注册 因为使用了directive
创建自定义指令,他接受两个参数(参1:创建自定义指令的名称,ps:不用加v 直接写名称就可以 否则会报错)
参2:是对象,对象里面写生命周期钩子函数
vue2中写法
在main.js中全局注册
// 1. 自定义指令
/*
自定义指令
适应 Vue.directive
第一个参数:指令名称
第二个参数:对象{}
*/
Vue.directive('focus', {
// 绑定 在绑定的时候开始调用 并且只调用一次 因为只会绑定一次
/*
每个都有两个参数
element,binding
*/
bind(el, binding) {
el.focus();
el.style.border="2px solid #f00"
console.log(el,binding);
},
// 节点在插入的时候调用
inserted() {},
// 在更新的时候调用
update() {},
// 在组件更新完成之后调用
componentUpdated() {},
// 解绑的时候调用
unbind() {
}
})
在组件中使用<input v-focus type="text">
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。