使用Vue开发一个实时性时间转换指令
前言
最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了。比如咱们今天要聊的这个话题:如何用vue开发一个实时性的时间转换指令?
接下来正文从这开始~
如上图所示(我是截取的某技术社区首页的部分页面),大家看到用红色边框勾选中的时间文字了吧。很多网站发布动态的时候,都会有一个相对本机时间转换后的相对时间。那你知道这个功能实现的背后原理是什么吗?如果有兴趣的,请备好瓜子,茶水,继续往下读。
一般在服务器的存储时间格式是unix时间戳,比如 2018-01-17 06:00:00的时间戳是1516140000。前端在拿到数据后,将它转换为可持续的时间格式再显示出来。为了显示出实时性,在一些社交类产品中,甚至会实时转换为几秒前、几分钟前、几小时前等不同的格式,因为这样比直接转换为年、月、日、时、分、秒,显得对用户更加友好,体验更人性化。
今天,我们就来实现这样一个vue自定义指令v-time,将表达式传入的时间戳实时转换为相对时间。为了便于演示效果,我们初始化时定义了两个时间。
首先来看html结构:
<div id="app" v-cloak> <div v-time="timenow"></div> <div v-time="timebefore"></div> </div>
以及初始化一个vue实例:
var app = new vue({ el:'#app', data:{ timenow:(new date()).gettime(), timebefore:686219755822 } })
timenow是目前的时间,timebefore是一个写死的时间:1991-09-30。
先来分析一下时间转换的逻辑:
- 1分钟以前,显示“刚刚”。
- 1分钟~1小时之间,显示“xx分钟前”。
- 1小时~1天之间,显示“xx小时前”。
- 1天~1个月(31天)之间,显示“xx天前”。
- 大于1个月,显示“xx年xx月xx日”。
这样罗列出来,逻辑就一目了然了。为了使判断更简单,我们这里统一使用时间戳进行大小判断。在写指令v-time之前,需要先写一系列与时间相关的函数 ,我们声明一个对象time,把它们都封装到里面。
var time = { //获取当前时间戳 getunix:function(){ var date = new date(); return date.gettime(); }, //获取今天0点0分0秒的时间戳 gettodayunix:function(){ var date = new date(); date.sethours(0); date.setminutes(0); date.setseconds(0); date.setmilliseconds(0); return date.gettime(); }, //获取今年1月1日0点0分0秒的时间戳 getyearunix:function(){ var 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:function(time){ var date = new date(time); var month = date.getmonth() + 1 < 10 ? '0' + (date.getmonth() + 1) : date.getmonth() + 1; var day = date.getdate() < 10 ? '0' + date.getdate() : date.getdate(); return date.getfullyear() + '-' + month + '-' + day; }, //转换时间 getformattime:function(timestamp){ var now = this.getunix(); // 当前时间戳 var today = this.gettodayunix(); // 今天0点的时间戳 var year = this.getyearunix(); // 今年0点的时间戳 var timer = (now - timestamp) / 1000; // 转换为秒级时间戳 var 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.ceil(timer/86400) + '天前'; }else{ tip = this.getlastdate(timestamp); } return tip; } }
当然,如果你对javascript的date类型不太了解,可以先去runoob.com上面了解下。
接着说回来,time.getformattime()方法就是自定义指令v-time所需要的,参数为毫秒级时间戳,返回已经整理好的时间格式的字符串。
最后,来看我们如何用vue自定义一个指令v-time:
vue.directive('time',{ bind:function(el, binding){ el.innerhtml = time.getformattime(binding.value); el.__timeout__ = setinterval(function(){ el.innerhtml = time.getformattime(binding.value); }, 60000) }, unbind:function(el){ clearinterval(el.__timeout__); delete el.__timeout__; } })
在bind钩子里,将指令v-time表达式的值binding.value作为参数传入time.getformattime()方法中得到格式化时间,在通过el.innerhtml写入指令所在元素。定时器el.__timeout__每分钟触发一次,更新时间,并且在unbind钩子里清除掉。
你可能会问,这个binding.value是什么?
当然,你可以通过console.log(binding)方法在控制台打印一下,就一目了然了。
在这里,我先补充下,自定义指令的选项是由几个钩子函数组成的,有bind、insert、update、componentupdated、unbind。而其中的bind和unbind只调用一次。每个钩子函数都有几个参数可用,比如我们上面用到的el和binding。
el指令所绑定的元素可以用来直接操作dom。而binding是一个对象,包含很多属性,如上图所示:
- name:指令名
- rawname:自定义指令
- value:指令的绑定值
- expression:绑定值的字符串形式
- modifiers:一个包含修饰符的对象
总结
在编写自定义指令时,给dom绑定一次性事件等初始动作,建议在bind钩子内完成,同时要在unbind内解除相关绑定。
以上所述是小编给大家介绍的使用vue开发一个实时性时间转换功能,希望对大家有所帮助