在vue中如何实现自定义指令directive
一、什么是自定义指令?
只要看到 v- 开头的,都是指令,不同的指令都有实现不同的功能,可以对普通DOM元素进行底层,这时候就该用到自定义指令,除了核心的内置指令外(比如:v-show、v-model),Vue也可以注册
自定义指令
自定义指令又分为:全局自定义指令、局部自定义指令、
二、使用自定义指令又分为了一下几种方式?
//会实例化一个指令,但这个指令没有参数
`v-xxx`
// -- 将值传到指令中,这个是有值的指令
`v-xxx="value"`
// -- 将字符串传入到指令中,如`v-html="'<p>内容</p>'"`
`v-xxx="'string'"`
// -- 传参数(`arg`),如`v-bind:class="className"`
`v-xxx:arg="value"`
// -- 使用修饰符(`modifier`)
`v-xxx:arg.modifier="value"`
三、如何注册自定义指令?
注册一个自定义指令有:全局自定义指令、局部自定义指令、
自定义的钩子函数
自定义指令也像组件那样存在钩子函数:
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用unbind
:只调用一次,指令与元素解绑时调用
所有的钩子函数的参数都有以下:
el
:指令所绑定的元素,可以用来直接操作 DOMbinding
:一个对象,包含以下 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 编译生成的虚拟节点
`oldVnode`:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
VNode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
全局自定义指令是在main.js中,通过 Vue.directive
进行注册
使用方法:
<div v-focus>自定义指令</div> //页面中的使用
// 注册一个全局自定义指令 `v-focus`
Vue.directive("focus", { //常用的一定要会,面试的时候面试官也是经常用的,不经常用的但是也要知道
bind(el, binding) {
//比较常用的
console.log("元素第一次绑定上时进行调用");
},
inserted(el, binding, VNode) {
//比较常用的
console.log("元素插入父节点时进行调用");
},
update(el, binding) {
//一般不经常使用
console.log("组件的 VNode 更新时进行调用");
},
componentUpdated(el, binding) {
//一般不经常使用
console.log("组件的 VNode 及子 VNode 全部更新后调用");
},
unbind(el, binding) {
//一般不经常使用
console.log("元素解绑时进行调用");
},
});
局部注册是在当前组件中,通过 directives
进行注册
使用方法:
<div v-focus>自定义指令</div> //页面中的使用
directives: {
focus: {
bind(el, binding) {
//比较常用的
console.log("元素第一次绑定上时进行调用");
},
inserted(el, binding, VNode) {
//比较常用的
console.log("元素插入父节点时进行调用");
},
update(el, binding) {
//一般不经常使用
console.log("组件的 VNode 更新时进行调用");
},
componentUpdated(el, binding) {
//一般不经常使用
console.log("组件的 VNode 及子 VNode 全部更新后调用");
},
unbind(el, binding) {
//一般不经常使用
console.log("元素解绑时进行调用");
},
},
},
四、应用场景
使用自定义组件组件可以满足我们日常一些场景,这里给出几个自定义组件的案例:
- 防抖动
- 图片懒加载
- 一键 Copy的功能
- 拖拽
拖拽
<div id="ab" v-drag></div> //要拖拽的那个div
//样式
#ab{
width: 100px;
height: 100px;
background-color: red;
position: absolute; //完成拖拽的话,需要给样式里边添加一个 position: absolute; 才行
}
//局部自定义指令
directives: {
drag: {
bind() {},
inserted(el) {
el.onmousedown = (e) => {
let x = e.clientX - el.offsetLeft;
let y = e.clientY - el.offsetTop;
document.onmousemove = (e) => {
let xx = e.clientX - x + "px";
let yy = e.clientY - y + "px";
el.style.left = xx;
el.style.top = yy;
};
el.onmouseup = (e) => {
document.onmousemove = null;
};
};
},
},
},