Vue 自定义指令
自定义指令的钩子函数
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作
- inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在与document中)
- update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用
- unbind:只调用一次,指令与元素解绑时调用
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(',')
}
})
<div v-test:msg.a.b.c="message"></div>
- el 指令绑定的元素,可以用来直接操作DOM
- binding 一个对象,包含以下属性:
- name 指令名
- value 指令的绑定值
- oldValue 指令绑定的前一个值,在update和componentUpdate钩子中可用。
- expression 绑定值的字符串形式
- arg 传给指令的参数
- modifiers 一个包含修饰符的对象
input 输入框失去焦点时,提交数据,点击取消不提交数据,但是blur是失去焦点事件,当点击button按钮时,也会触发blur这个失去焦点事件,达不到我们的预期效果,下面使用vue指令 来实现这一效果。
判断绑定元素中是否包含我们当前点击的元素,如果包含,就返回false,否则就执行失去焦点事件的回调
Vue.directive("clickoutside", {
bind: function (el, binding) {
function documentHandler(e) {
console.log(e);
console.log(el.contains(e.target));
if (el.contains(e.target)) {
return false;
}
if (binding.expression) {
binding.value()
}
}
el._vueClickOutside_ = documentHandler;
document.addEventListener("click", documentHandler);
},
unbind: function (el) {
document.removeEventListener("click", el._vueClickOutside_);
delete el._vueClickOutside_;
},
});
new Vue({
...
methods:{
handlerSubmit:function(){
console.log("提交数据")
},
}
...
})
<div v-clickoutside="handlerSubmit">
<input ref="input" type="text" @blur="handlerSubmit">
<button @click="handlerCancel">取消</button>
</div>
实时时间转换指令
- 1分钟内,“刚刚”
- 1分钟-1小时 “分钟”
- 1小时-1天 “小时”
- 1天-1月 “天”
- 年月日
时间处理对象time
export default const time = {
// 当前时间戳
getTime(){
const date = new Date()
return date.getTime()
},
// 今天0时0分0秒的时间戳
getTodayTime(){
const date = new Date()
date.setHours(0)
date.setSeconds(0)
date.setMinutes(0)
date.setMilliseconds(0)
return date.getTime()
},
// 今年1月1日0时0分0秒的时间戳
getYearTime(){
const date = new Date()
date.setMonth(0)
date.setDate(1)
date.setHours(0)
date.setMinutes(0)
date.setSeconds(0)
date.setMilliseconds(0)
return date.getTime()
},
// 标准年月日
getLastDate(time){
const date = new Date(time);
const month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1 ;
const day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
return date.getFullYear() + '-' + month + '-' + day;
},
getFormatTime(timestamp){
const now = this.getTime();
const today = this.getTodayTime();
// const year = this.getYearTime();
const timer = (now - timestamp)/1000;
let tip="";
if(timer<=0){
tip="刚刚";
}else if(Math.floor(timer/60) <=0){
tip = "刚刚";
}else if(timer <3600){
tip = Math.floor(timer/60) + '分钟前';
}else if(timer>3600 && (timestamp-today > 0)){
tip = Math.floor(timer/3600) + "小时前";
}else if(timer/86400<=31){
tip = Math.floor(timer
/86400) + '天前';
}else{
tip = this.getLastDate(timestamp);
}
return tip;
}
}
指令
隔一分钟 调用一次
Vue.directive("time",{
bind(el,binding){
el.innerHTML = mytime.getFormatTime(binding.value);
el._timeout_ = setInterval(()=>{
el.innerHTML = mytime.getFormatTime(binding.value)
},60000)
},
unbind(el){
clearInterval(el._timeout_);
delete el._timeout_
}
})
<div>
<div v-time="timeNow"></div>
<div v-time="timebefore"></div>
</div>
const mybirthday = {
//根据时间戳计算当前多少天
getFormatDay(value) {
const nowTime = new Date().getTime()
return Math.floor((nowTime-value)/86400000) + "天";
},
// 根据多少天计算出几年几月几日(即出生几岁几月几日)
getYearMonthDay(value){
const year = Math.floor(value/365)
const month = Math.floor(value%365/30)
const day = Math.floor(value%365%30)
return year + "岁" + month + "个月" + day + "天"
}
};
export default mybirthday;