「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」
请移步 vue-cli自定义指令-从实例入门,掌握最基础的语法概念在来阅读此篇。
参数熟悉
也是直接从一个demo开始进一步了解这些指令,这里采用局部注册。
我们使用自定义指令v-learn将钩子函数的参数打印出来,这里打印的是inserted钩子函数的参数,其他钩子函数(也叫生命周期)也同理,只是调用时间、次数不同(inserted里可以写各种js语句)。
<template>
<div class="container">
<div v-learn:hello.a.b="message">12321</div>
</div>
</template>
<script>
export default {
data() {
return {
message: "菜鸟教程!",
};
},
directives: {
learn: {
inserted(el, binding, vnode) {
console.log("el --------", el);
console.log("name --------", binding.name);
console.log("value --------", binding.value);
console.log("expression --------", binding.expression);
console.log("arg --------", binding.arg);
console.log("modifiers --------", binding.modifiers);
console.log("vnode --------", vnode);
},
},
},
};
</script>
打印结果如下:
实际应用
v-drag
使用自定义指令v-drag,实现拖拽功能,可在页面可视区域任意拖拽元素,这里我采用的是局部注册,关键代码如下:
directives: {
drag: {
inserted: function (el) {
el.style.cursor = "move";
el.onmousedown = function (e) {
let disx = e.pageX - el.offsetLeft;
let disy = e.pageY - el.offsetTop;
document.onmousemove = function (e) {
console.log(e);
let x = e.pageX - disx;
let y = e.pageY - disy;
let maxX =
document.body.clientWidth -
parseInt(window.getComputedStyle(el).width);
let maxY =
document.body.clientHeight -
parseInt(window.getComputedStyle(el).height);
if (x < 0) {
x = 0;
} else if (x > maxX) {
x = maxX;
}
if (y < 0) {
y = 0;
} else if (y > maxY) {
y = maxY;
}
el.style.left = x + "px";
el.style.top = y + "px";
};
document.onmouseup = function () {
document.onmousemove = document.onmouseup = null;
};
};
},
},
},
使用时只需给元素加上 v-drag指令
<div class="drag" v-drag></div>
注:拖动元素必须设置position属性
.drag {
margin-top: 50px;
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
background: rgb(252, 220, 220);
position: relative;
}
v-relativeTime
使用自定义指令v-relativeTime,实现将时间戳转换为相对时间的功能 即我们常常在各种网站或者APP上看到的,当有一条新内容发布后,不直接显示发布时间,而是显示为几分钟前,刚刚等这样的相对时间。
实现思路也很简单,获取指令上赋值的时间戳,与当前时间作比较,通过差值判断相对时间显示的文字,将文字插入至元素中
关键代码如下: 在main.js中全局注册
Vue.directive('relativeTime', {
bind(el, binding) {
const Time = {
// 获取当前时间戳
getUnix() {
const date = new Date();
return date.getTime();
},
// 获取今天0点0分0秒的时间戳
getTodayUnix() {
const date = new Date();
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date.getTime();
},
// 获取今年1月1日0点0分0秒的时间戳
getYearUnix() {
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 year = date.getFullYear();
const month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
const day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
return year + '-' + month + '-' + day;
},
// 转换时间
getFormatTime(timestamp) {
const now = this.getUnix(); // 当前时间戳
const today = this.getTodayUnix(); // 今天0点0分0秒时间戳
const year = this.getYearUnix(); // 今年1月1日0点0分0秒的时间戳
const timer = (now - timestamp) / 1000; // 获取传递进来的时间和当前时间的差值,并转换为秒级时间戳
let tip;
if(timer < 60 || 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;
}
}
el.innerHTML = Time.getFormatTime(binding.value)
el.__timeout__ = setInterval(() => {
el.innerHTML = Time.getFormatTime(binding.value)
}, 6000)
},
unbind(el) {
clearInterval(el.innerHTML)
delete el.__timeout__
}
})
使用时只需给元素加上 v-relativeTime指令,将时间戳传给该指令,便会自动计算出相对于当前时间的时间
<div v-relativeTime="1636083312221"></div>
显示为:
在实际的开发中,根据项目需求创建更高级灵活的自定义指令,使你的代码更加简洁。 当我们在项目中需要全局注册多个自定义指令时,则会造成main.js中代码臃肿,可以考虑批量注册,详见下文。