在写vue项目的时候,我们经常需要对后台返回的数据进行大量的渲染操作,其中就包含了大量的对特殊数据的进一步处理,比如说时间戳、图片地址、特殊数据显示等等特殊数据处理改进。
其实遇到这种情况,通过Vue过滤器filter,或者给Vue下面原型方法里添加自定义方法都可以解决我们的问题,不过我们要说的是自定义指令,前面两种方式有他们好处,自定义指令也有自己独特的优点,比如说自定义指令自身就包含一系列生命周期钩子函数,能够在不同的生命周期函数中传递参数,添加修饰符等操作,因此自定义指令也能够处理更复杂的数据。
下面我们就来介绍一下自定义指令的简单实践,通过简单的例子,大家肯定能更进一步的了解自定义指令的使用。
1.首先我们要先了解一下自定义指令的基本结构,这里首先是全局定义一个自定义指令,这个自定义指令的名称是demo。
Vue.directive('demo', { //自定义指令钩子函数
bind: function() { //被绑定钩子函数
},
inserted: function() { //绑定到节点钩子函数
},
update: function() { //组件更新钩子函数
},
componentUpdated: function() { //组件更新完成钩子函数
},
unbind: function() { //解绑钩子函数
}
})
ps(转载自vue官网):一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
2.每个自定义指令的生命周期都可以接受一下以下参数,即 el
、binding
、vnode
和 oldVnode。
指令钩子函数会被传入以下参数(转载自vue官网):
el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
:一个对象,包含以下属性:
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
钩子中可用
3.在了解了自定义指令的生命周期函数和函数参数之后,下面我们就来自己写一个自定义指令的例子来进一步了解自定义指令的用法。(我们来写一个格式化时间戳的自定义指令v-timeformat)
①首先我们先来写好html结构,以引入vue文件的形式来写这个例子,同时初始化vue实例对象。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
new Vue({
el:'#app',
data: function () {
return {
timeStamp:1335562531231
}
},
created: function () {
}
})
</script>
</body>
</html>
②编写v-timeformat自定义指令。
Vue.directive('timeformat', {
bind: function (el, binding, vnode) {//这里只在bind生命周期函数中进行定义和操作,大家也可以在其他自定义指令的生命周期函数中尝试进行扩展和修改。
function initTime(num){//判断数字是否大于10
return num < 10 ? '0'+num : num;
}
function checkTime(timeStamp){//格式化时间戳函数,大家也可以根据实际需求进行扩展和改写
var time = new Date(timeStamp);
var year = time.getFullYear();
var month = time.getMonth()+1;
var day = time.getDate();
var hour = time.getHours();
var minute = time.getMinutes();
var second = time.getSeconds();
if(binding.modifiers.small){//判断修饰符是否存在,存在即返回指定时间格式
return year+'-'+initTime(month)+'-'+initTime(day);
}else if(binding.modifiers.big){
return year+'-'+initTime(month)+'-'+initTime(day)+' '+initTime(hour)+':'+initTime(minute)+':'+initTime(second);
}else{
return year+'-'+initTime(month)+'-'+initTime(day)+' '+initTime(hour)+':'+initTime(minute)+':'+initTime(second);
}
}
el.innerHTML = checkTime(binding.value);//格式化之后的时间信息插入到当前元素中
binding.arg == '' ? el.style.color = '#333' : el.style.color = binding.arg;//通过传递参数来改变元素字体颜色
}
})
③使用v-timeformat自定义指令。
ps:
- 在使用自定义指令时要在我们定义的自定义指令名称前加v-。
- 自定义指令和vue系统自带指令类似,可以通过传递参数来改变元素状态,这里传入orange表示把这个元素的字体颜色改成橙黄色
- 这里紧跟在生命周期函数参数之后的是修饰符,传递不同的修饰符来选择要格式化的不同的时间戳的样式和格式。
<div v-timeformat:orange.small="timeStamp"></div>
总结一下:vue自定义指令虽然并不是很难,但是在实际开发过程中有些时候会被开发者忽略,其实在使用Vue的过程中,并不一定要指定使用某一种特定的数据处理方式方法,要根据项目需求,采用不同的合理方式来优化我们的代码和项目,方便我们更好的高效的进行工作。