写在文本前:相信在作vue的项目,你确定接触了指令,咱们经常使用vue内置的一些指令,好比v-model,v-text,v-if,v-show等等,可是这些内置指令不在本文的讲解范畴,本文想说的是其自定义指令。思考一下,自定义指令咱们用在哪里?是否是一会儿想不出来,感受作通常的项目不多用到指令呢,想不到指令用在哪!!由于咱们的确不多用,但不是说不会用。看官方api文档里有这么一句话:普通 DOM 元素进行底层操做,这时候就会用到自定义指令。也就是说咱们在操做普通DOM的时候有可能会用到。在作项目的时候,咱们有不少种方法来替代自定义指令,因此让咱们忽略了vue自定义指令的用处。下边咱们一步步来了解vue自定义指令。javascript
(一、输入框焦点自动触发。
(一、输入框的电话号码,邮箱,身份证号码等的校验。html
上面这几个场合,咱们在作项目的时候彻底能够用其余方法代替,可是vue自定义指令能让咱们作到一劳永逸,作到一处定义,全局调用。使其代码简洁高效,维护方便。接下来,咱们会一步步深刻vue自定义指令。vue
/* 自定义指 */ import Vue from 'vue' /** * 模板 * v-lang * 五个注册指令的钩子函数 */ Vue.directive('mydirective', { /** * 1.被绑定 * 作绑定的准备工做 * 好比添加事件监听器,或是其余只须要执行一次的复杂操做 */ bind: function(el, binding, vnode) { console.log('1 - bind'); }, // 2.绑定到节点 inserted: function(el, binding, vnode) { console.log('2 - inserted'); }, /** * 3.组件更新 * 根据得到的新值执行对应的更新 * 对于初始值也会调用一次 */ update: function(el, binding, vnode, oldVnode) { console.log('3 - update'); }, // 4.组件更新完成 componentUpdated: function(el, binding, vnode, oldVnode) { console.log('4 - componentUpdated'); }, /** * 5.解绑 * 作清理操做 * 好比移除bind时绑定的事件监听器 */ unbind: function(el, binding, vnode) { console.log('5 - bind'); } }) /** 钩子函数 一、bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数能够定义一个绑定时执行一次的初始化动做。 二、inserted:被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于document中)。 三、update:被绑定于元素所在的模板更新时调用,而不管绑定值是否变化。经过比较更新先后的绑定值,能够忽略没必要要的模板更新。 四、componentUpdated:被绑定元素所在模板完成一次更新周期时调用。 五、unbind:只调用一次,指令与元素解绑时调用。 */
执行顺序:
页面加载时java
bind
inserted
组件更新时node
update
componentUpdated
卸载组件时express
unbind
官方地址请移步至,directive,上面只是作了个简单的说明,接下来咱们详细的介绍vue自定义指令的各个钩子函数到底如何触发。api
就我的而言, bind和update也许是这五个里面最有用的两个钩子了.这个也是咱们下边主要要说的2个钩子函数。其它函数不经常使用,我也没搞明白。ide
bind:只调用一次,指令第一次绑定到元素时调用。在这里能够进行一次性的初始化设置。函数
<input id="input1" v-mydirective> // html元素 Vue.directive('mydirective', { bind: function(el, binding, vnode) { el.style.border = "1px solid red" } }
上面代码的效果就是输入框的边框变成了1像素的红色。固然你也能够设置其它试试。测试
<input id="input1" v-mydirective> // html元素 Vue.directive('mydirective', { bind: function(el, binding, vnode) { el.addEventListener('click', function (event) { alert('hellow world') }) } }
在bind钩子函数里,咱们能够添加一些事件,在其某种条件下触发(好比点击事件,键盘事件),如上代码,点击input输入框就会弹出 “hellow world”。至于bind里面的参数的含义,建议本身动手输入出来看看。很简单是吧,下边咱们来些稍微复杂一点的。看以下代码:
指令钩子函数会被传入如下参数:
/** 钩子函数的参数:(el, binding, vnode, oldVnode) el:指令所绑定的元素,能够用来直接操做 DOM 。 binding:一个对象,包含如下属性 name:指令名,不包含v-的前缀; value:指令的绑定值;例如:v-my-directive="1+1",value的值是2; oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子函数中可用,不管值是否改变均可用; expression:绑定值的字符串形式;例如:v-my-directive="1+1",expression的值是'1+1'; arg:传给指令的参数;例如:v-my-directive:foo,arg的值为 'foo'; modifiers:一个包含修饰符的对象;例如:v-my-directive.a.b,modifiers的值为{'a':true,'b':true} vnode:Vue编译的生成虚拟节点; oldVnode:上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。 */
这里咱们着重注意一下,binding对象下的value,oldValue,arg,expression,modifiers这几个属性,根据这几个属性,咱们能够作到更强大的自定义指令,下边咱们参考案例来讲:
<div v-mydirective:left="100" id=”box"></div> // html元素
Vue.directive('mydirective', {
bind: function(el, binding, vnode) {
el.style.position = 'fixed';
const s = (binding.arg === 'left' ? 'left' : 'top');
el.style[s] = binding.value + 'px';
}
}
上面的代码是使id=”box“的这个div元素绝对定位了,并且设置了left的值为100px;
update:每当元素自己更新(可是子元素还未更新)时触发。这句话怎么理解呢?咱们用案例来讲明,以下:
<template> <div id="box"> <input v-model="myname" v-mydirective/> </div> <template> export default { data(){ return{ myname:"zhangshan" } }, directives:{ 'mydirective':{ update: function(el, binding, vnode, oldVnode) { console.log('update更新了'); } } } }
上边代码,输入框默认值是"zhangshan",若是咱们修改了myname值,那么就会触发update函数的执行,输出“update更新了”
再来个复杂一点的案例以下:
<template> <div id="box"> <input type="text" v-model="myname" v-mydirective="{type:'name',val:myname}"/> <input type="text" v-model="myemail" v-mydirective="{type:'email',val:myemail}"/> </div> <template> export default { data(){ return{ myname:"zhangshan", myemail:'***@163.com' } }, directives:{ 'mydirective':{ update: function(el, binding, vnode, oldVnode) { //update:指令的值可能发生了改变,也可能没有。可是你能够经过比较更新先后的值来忽略没必要要的模板更新 if(binding.oldValue.val != binding.value.val){// 进行判断,避免同时触发多个判断 let checkStatus = true;// 定义验证状态 局部变量 if(binding.value.type == 'name'){ if(binding.value.val.length>5){ checkStatus = false; console.log("输入的姓名长度大于5了") } } if(binding.value.type == 'email'){// 验证邮箱 if(!/^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a- z0-9]+$/g.test(binding.value.val)){ checkStatus = false; } } if(checkStatus){ el.style.border = "1px solid #333";//验证经过input边框颜色就变成#333 }else{ el.style.border = "1px solid red";//验证不经过input边框颜色就变成红色 } } } } } }
上边的案例,咱们经过bind下的modifiers属性实现。modifiers:一个包含修饰符的对象;例如:v-my-directive.a.b,modifiers的值为{'a':true,'b':true}。这样咱们在update钩子函数里根据所传入的type类型作判断来执行哪一个验证方法。
inserted:被绑定元素插入父节点时调用(父节点存在便可调用,没必要存在于document中)。
<input id="input1" v-mydirective> // html元素 Vue.directive('mydirective', { inserted: function(el, binding, vnode) { el.focus()//输入框自动获取焦点 } }
对于钩子函数 inserted,我也是只知其一;不知其二,所用的很少,可是有个经常使用的方法是写在这里面的,就是输入框自动获取焦点,也就是上面的代码。
据文档所说,插入父节点时调用 inserted,来个测试。
bind: function (el) { console.log(el.parentNode) // null console.log('bind') }, inserted: function (el) { console.log(el.parentNode) // <div id="login">...</div>这个元素是指令所在元素的父元素,具体根据本身的写法不一样 console.log('inserted') }
分别在两个钩子函数中输出父节点:bind 时父节点为 null,inserted 时父节点存在。
// 4.组件更新完成 componentUpdated: function(el, binding, vnode, oldVnode) { console.log('4 - componentUpdated') }, /*** 5.解绑 * 作清理操做 * 好比移除bind时绑定的事件监听器 */ unbind: function(el, binding, vnode) { console.log('5 - bind'); }
对于这2个钩子函数,没有作太多的研究,unbind可能会用到,用于释放实例资源占用等操做。
关于vue.js指令大体也就说这么多吧,若是错误,欢迎指正拍砖......