在vue2.0中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通DOM元素进行底层操作,这时候就会用到自定义指令。
自定义指令最重要的两个部分就是钩子函数和钩子函数对应的参数。
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
钩子函数的参数
便于理解的小案例
好了为了便于理解,我们先看一下在自定义指令中,我们能接收到的
<div id="app" v-demo="message"></div>
<script type="text/javascript" src='https://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/teamFrighting/js/vue.min.js'></script>
<script type="text/javascript">
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'argument: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#app',
data: {
message: 'hello!'
}
})
页面显示:
从输出的结果可以看出,在自定义指令中能接收到传入的参数和元素等等
再理解一下自定义指令各个钩子的区别
<div id="app" >
<input type="text" v-demo="message">
</div>
<script type="text/javascript" src='https://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/teamFrighting/js/vue.min.js'></script>
<script type="text/javascript">
Vue.directive('demo', {
bind: function (el, binding) {
el.value=binding.value+'我是饭饭';
console.log(el.value)
},
inserted:function (el, binding) {
el.value=binding.value+'你叫什么名字?';
console.log(el.value)
},
update:function (el, binding) {
//暂时没有很好的例子
console.log(el.value)
},
componentUpdated:function (el, binding) {
//暂时没有很好的例子
console.log(el.value)
},
unbind:function (el, binding) {
//暂时没有很好的例子
console.log(el.value)
}
})
new Vue({
el: '#app',
data: {
message: 'hello,'
}
})
页面显示:
从页面显示可以看出bind: 一旦指令附加到元素时触发,inserted: 一旦元素被添加到父元素时触发以及两者的区别,这两者也是我们开发过程中常用的。
常见自定义指令:
1、在图片未完成加载前,用随机的背景色占位,图片加载完成后才直接渲染出来。
<div id="app" >
<div v-img='val.url' v-for="val in list"></div>
</div>
<script type="text/javascript" src='https://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/teamFrighting/js/vue.min.js'></script>
<script type="text/javascript">
Vue.directive('img', {
inserted:function (el, binding) {
var color = Math.floor(Math.random()*1000000);
el.style.backgroundColor = "#" + color;
var img = new Image();
img.src = binding.value;
img.onload = function(){
el.style.backgroundImage = 'url('+ binding.value +')'
}
}
})
new Vue({
el: '#app',
data: {
list:[
{
url:'http://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/Billboard/img/tan04.jpg'
},
{
url:'http://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/Billboard/img/tan03.jpg'
},
{
url:'http://i0.jrjimg.cn/zqt-red-1000/focus/focus2017YMZ/Billboard/img/tan04.jpg'
}
]
}
})
案例效果:
2、自定义指令的第二用处是用于集成第三方插件。
比如写文档通常会用到highlight.js,我们可以直接将其封装为一个自定义指令,这样highlight.js就变成了Vue的一个新功能
但凡遇到第三方插件如何与Vue.js集成的问题,都可以尝试用自定义指令实现