想看上一节的请点击上面的链接,(被csdn吞了两次的文章,加起来有半天的工作量了)
自定义指令
在第五章里我们已经介绍过了许多Vue内置的指令,比如v-if、v-show等,这些丰富的内置指令能满足我们绝大部分业务需求,不过在需要一些特殊的功能时,我们仍然希望能对DOM进行底层的操作,这时就要用到自定义指令。
基本用法
自定义指令的注册方法和组件很像,也分全局注册和局部注册,比如注册一个v-focus的指令,用于在<input>、<textarea>元素初始化时自动获得焦点,两种写法分别时:
写法与组件的基本类似,只是方法名由component改为了directive。上例只是注册了自定义指令v-focus,还没有实现具体功能,下面具体介绍自定义指令的各个选项。
自定义指令的选项是由几个钩子函数组成的,每个都是可选的。
bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化操作。
inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。
update:被绑定元素所在模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
componentUpdate:被绑定元素所在模板完成一次更新周期时调用。
unbind:只调用一次,指令与元素解绑时调用。
可以根据需求在不同的钩子函数内完成逻辑代码,例如上面的v-focus,我们希望在元素插入父节点时就调用,那用到最好是inserted。示例代码如下:
<div id="app">
<input type="text" v-focus>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
Vue.directive('focus',{
inserted:function(el){
// 聚焦元素
el.focus();
}
});
var app = new Vue({
el:'#app'
})
</script>
在浏览器显示的效果如下:
可以看到,打开这个页面,input输入框就自动获得了焦点,成了可输入状态。
每个钩子函数都有几个参数可用,比如上面我们用到了el。它们的含义如下:
el 指令所绑定的元素,可以直接操作DOM。
binding 一个对象,包含一下属性
vnode Vue编译生成的虚拟节点,在进阶篇中介绍
oldVnode 上一个虚拟节点仅在update和componentUpdated钩子中可用。
下面结合和了以上参数的具体示例:
<div id="app">
<div v-test:msg.a.b="message"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
Vue.directive('test',{
bind:function(el,binding,vnode){
var keys=[];
for(var i in vnode){
keys.push(i);
}
el.innerHTML =
'name:'+ binding.name+'<br>'+
'value:'+binding.value+'<br>'+
'expression:'+binding.expression+'<br>'+
'argument:'+binding.arg+'<br>'+
'modifiers:'+JSON.stringify(binding.modifiers)+'<br>'+
'vnode keys:'+keys.join(',')
}
});
var app = new Vue({
el:'#app',
data:{
message:'some text'
}
})
</script>
执行后,<div>的内容会使用innerHTML重置,结果为:
在大多数使用场景,我们会在bind钩子里绑定一些事件,比如在document上使用addEventListener绑定,在unbind里用removeEventListener解绑,比较典型的示例就是让这个元素随着鼠标拖拽。在后面的8.2节中,我们会详细介绍。
如果需要多个传值,自定义指令也可以传入一个JavaScript对象字面量,只要是合法类型的JavaScript表达式都可以的。示例代码如下:
Vue 2.x移除了大量Vue 1.x自定义指令的配置。在使用自定义指令时,应该充分理解业务需求,因为很多时候你需要的可能并不是自定义指令,而是组件。在下一节中,我们结合两个经典的示例来进一步了解自定义指令的使用场景和用法。
实战
开发一个可以从外部关闭的下拉菜单
网页中很多常见的下拉菜单,如下图
点击用户头像和名称,会弹出一个下拉菜单,然后点击页面中其他空白区域(除了菜单本身外),菜单就关闭了。
先来分析一下如何实现:
该示例有两个特点,一是点击下拉菜单本身是不会关闭的,二是点击下拉菜单以外的所有区域都要关闭。点击所有区域可以在document上绑定click事件来实现,同时只要过滤出是否点击目标元素内部的元素即可。
剩下的先不讲了。