如果Vue内置的指令不能满足功能需求的时候,可以进行自定义指令。
自定义指令的使用场景就是操作基础DOM,实现功能需求。
1.关于自定义指令的钩子函数
自定义指令的五个钩子函数都是可选的,比如 v-once 指令。
-
bind
指令第一次绑定到元素上;只调用一次;可以做相关初始化的操作;
-
inserted
被绑定的元素插入到其父元素节点时调用;
-
update
当所在组件的VNode更新时调用;但是update和VNode的更新顺序不定,所以需要比较;
-
componentUpdated
指令所在组件的VNode及其子VNode全部更新完成后调用;
-
unbind
解绑;只调用一次
2.写法
和组件一样,自定义指令也分全局指令和局部指令。
全局指令:
Vue.directive('my-directive', {
// 只调用一次,指令第一次绑定到元素时调用
bind (el, binding, vnode) {
},
// 被绑定元素插入父节点时调用
inserted (el, binding, vnode) {
console.log('inserted')
},
// 所在组件的 VNode 更新时调用
update (el, binding, vnode) {
console.log('update')
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用
componentUpdated (el, binding, vnode) {
console.log('componentUpdated')
},
unbind (el, binding, vnode) {
console.log('unbind')
}
});
局部指令:
@Component({
components: {
child,
},
directives: {
'my-directive': {
// 只调用一次,指令第一次绑定到元素时调用
bind(el, binding, vnode) {},
// 被绑定元素插入父节点时调用
inserted(el, binding, vnode) {
console.log("inserted");
},
// 所在组件的 VNode 更新时调用
update(el, binding, vnode) {
console.log("update");
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用
componentUpdated(el, binding, vnode) {
console.log("componentUpdated");
},
unbind(el, binding, vnode) {
console.log("unbind");
},
},
},
})
3.自定义指令的模块化
// module-directive.js
export default {
// 只调用一次,指令第一次绑定到元素时调用
bind(el, binding, vnode) {},
// 被绑定元素插入父节点时调用
inserted(el, binding, vnode) {
console.log("inserted");
},
// 所在组件的 VNode 更新时调用
update(el, binding, vnode) {
console.log("update");
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用
componentUpdated(el, binding, vnode) {
console.log("componentUpdated");
},
unbind(el, binding, vnode) {
console.log("unbind");
}
}
创建好模块化的指令后,通过index.js管理指令:
import myDirective from './modules/myDirective'
export { myDirective }
统一管理模块化指令后,在main.js中进行全局注册:
import * as directives from './directives'
Object.keys(directives).forEach(index => Vue.directive(index, directives[index]))
全局注册后,即可通过 v-DIRECTIVE_NAME使用。
需要注意的是,在翻其他博主的文章时,有提到自定义指令不能在数据更新的时候同步响应。
这个问题是和自定义指令的钩子函数有关,具体情况需要根据自己指令的需求去调整。