directive 指令
介绍
主要作用是对 dom
元素进行底层的操作。如 vue
自带的 v-if、v-show、v-for、v-model
等。
指令分为全局指令和局部指令,全局指令是注册在 Vue.directive
下,局部是放在组件的 directives: {}
对象中。
指令的钩子函数
bind
只调用一次,指令第一次绑定到元素时调用- 例如
copy
指令
- 例如
inserted
被绑定元素插入父节点时调用- 例如
focus
指令
- 例如
update
所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前componentUpdated
指令所在组件的 VNode 及其子 VNode 全部更新后调用unbind
只调用一次,指令与元素解绑时调用- 例如
copy
的解绑指令
- 例如
指令钩子函数会被传入以下参数:
el
:指令所绑定的元素,可以用来直接操作DOM
。binding
:一个对象,包含以下property
:name
:指令名,不包括v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为 2。oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为 "1 + 1
"。arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为 "foo
"。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
vnode
:Vue 编译生成的虚拟节点。移步VNode API
来了解更多详情。oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
JS
Vue.directive('demo',{
// 当指令绑定到 HTML 元素上时触发.**只调用一次**
bind() {
console.log('bind triggerd')
},
// 当绑定了指令的这个HTML元素插入到父元素上时触发(在这里父元素是 `div#app`)**.但不保证,父元素已经插入了 DOM 文档.**
inserted() {
console.log('inserted triggerd')
},
// 所在组件的`VNode`更新时调用.
updated() {
console.log('updated triggerd')
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
componentUpdated() {
console.log('componentUpdated triggerd')
},
// 只调用一次,指令与元素解绑时调用.
unbind() {
console.log('unbind triggerd')
}
})
Vue.directive('demo',{
// 当指令绑定到 HTML 元素上时触发.**只调用一次**
bind() {
console.log('bind triggerd')
},
// 当绑定了指令的这个HTML元素插入到父元素上时触发(在这里父元素是 `div#app`)**.但不保证,父元素已经插入了 DOM 文档.**
inserted() {
console.log('inserted triggerd')
},
// 所在组件的`VNode`更新时调用.
updated() {
console.log('updated triggerd')
},
// 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
componentUpdated() {
console.log('componentUpdated triggerd')
},
// 只调用一次,指令与元素解绑时调用.
unbind() {
console.log('unbind triggerd')
}
})
业务中常用的自定义指令
v-wave
点击水波纹效果v-copy
点击复制v-loading
加载中v-debounce
按钮防抖v-lazyload
图片懒加载v-draggable
dom 拖拽v-auth
权限控制
实现 copy 指令
JS
// directive/Clipboard.js
import Clipboard from "clipboard"; // 三方js插件
export default {
/**
* el 指令所绑定的元素,除el以外参数都为只读属性
* binding 可以设置指令信息的对象,如 value,v-copy="value"
* vnode Vue 编译生成的虚拟节点
*/
bind(el, binding = {}, vnode) {
// 设置样式
el.style.cursor = 'copy'
// 实例化 clipboard
const clipboard = new Clipboard(el, {
text: () => binding.value
})
clipboard.on('success', e => {
console.log("已复制到剪切板");
})
clipboard.on('error', e => {
console.log("复制失败");
})
},
// 需要 coply 内容更新时调用,将更新后的值绑定到 clipboard 对象上
update(el, binding) {
el.__clipboard__.text = () => binding.value
},
// 当dom被移除(比如组件销毁)时,解绑,防止内存泄漏
unbind(el, binding) {
el.__clipboard__.destroy();
delete el.__clipboard__;
}
}
// directive/Clipboard.js
import Clipboard from "clipboard"; // 三方js插件
export default {
/**
* el 指令所绑定的元素,除el以外参数都为只读属性
* binding 可以设置指令信息的对象,如 value,v-copy="value"
* vnode Vue 编译生成的虚拟节点
*/
bind(el, binding = {}, vnode) {
// 设置样式
el.style.cursor = 'copy'
// 实例化 clipboard
const clipboard = new Clipboard(el, {
text: () => binding.value
})
clipboard.on('success', e => {
console.log("已复制到剪切板");
})
clipboard.on('error', e => {
console.log("复制失败");
})
},
// 需要 coply 内容更新时调用,将更新后的值绑定到 clipboard 对象上
update(el, binding) {
el.__clipboard__.text = () => binding.value
},
// 当dom被移除(比如组件销毁)时,解绑,防止内存泄漏
unbind(el, binding) {
el.__clipboard__.destroy();
delete el.__clipboard__;
}
}
JS
// directive/index.js
import Clipboard from './Clipboard'
export default {
install (Vue) {
Vue.directive('copy', Clipboard)
}
}
// directive/index.js
import Clipboard from './Clipboard'
export default {
install (Vue) {
Vue.directive('copy', Clipboard)
}
}
JS
// main.js
import Clipboard from "./directive/Clipboard";
Vue.use(Clipboard)
// main.js
import Clipboard from "./directive/Clipboard";
Vue.use(Clipboard)