微信号:imooc-com

介绍:慕课网是一个超酷的互联网、IT技术免费学习平台,创新的网络一站式学习、实践体验;服务及时贴心,内容专业、有趣易学。专注服务互联网工程师快速成为技术高手!

用Vue开发一个实时性时间转换功能,看这篇文章就够了

2018-05-30 20:15 闰土大叔


前言


最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了。比如咱们今天要聊的这个话题:如何用Vue开发一个实时性的时间转换指令?


接下来正文从这开始



图片描述

如上图所示(我是截取的某技术社区首页的部分页面),大家看到用红色边框勾选中的时间文字了吧。很多网站发布动态的时候,都会有一个相对本机时间转换后的相对时间。那你知道这个功能实现的背后原理是什么吗?如果有兴趣的,请备好瓜子,茶水,继续往下读。


一般在服务器的存储时间格式是Unix时间戳,比如 2018-01-17 06:00:00的时间戳是1516140000。前端在拿到数据后,将它转换为可持续的时间格式再显示出来。为了显示出实时性,在一些社交类产品中,甚至会实时转换为几秒前、几分钟前、几小时前等不同的格式,因为这样比直接转换为年、月、日、时、分、秒,显得对用户更加友好,体验更人性化。


今天,我们就来实现这样一个Vue自定义指令v-time,将表达式传入的时间戳实时转换为相对时间。为了便于演示效果,我们初始化时定义了两个时间。


首先来看html结构:

 
           
  1. <div id="app" v-cloak>

  2.  <div v-time="timeNow"></div>

  3.  <div v-time="timeBefore"></div>

  4. </div>

以及初始化一个Vue实例:

 
           
  1. var app = new Vue({

  2.  el:'#app',

  3.  data:{

  4.  timeNow:(new Date()).getTime(),

  5.  timeBefore:686219755822

  6.  }

  7. })

timeNow是目前的时间,timeBefore是一个写死的时间:1991-09-30。

先来分析一下时间转换的逻辑:

  • 1分钟以前,显示“刚刚”。

  • 1分钟~1小时之间,显示“xx分钟前”。

  • 1小时~1天之间,显示“xx小时前”。

  • 1天~1个月(31天)之间,显示“xx天前”。

  • 大于1个月,显示“xx年xx月xx日”。


这样罗列出来,逻辑就一目了然了。为了使判断更简单,我们这里统一使用时间戳进行大小判断。在写指令v-time之前,需要先写一系列与时间相关的函数 ,我们声明一个对象Time,把它们都封装到里面。


 
           
  1.  var Time = {

  2.  //获取当前时间戳

  3.  getUnix:function(){

  4.  var date = new Date();

  5.  return date.getTime();

  6.  },

  7.  //获取今天0点0分0秒的时间戳

  8.  getTodayUnix:function(){

  9.  var date = new Date();

  10.  date.setHours(0);

  11.  date.setMinutes(0);

  12.  date.setSeconds(0);

  13.  date.setMilliseconds(0);

  14.  return date.getTime();

  15.  },

  16.  //获取今年1月1日0点0分0秒的时间戳

  17.  getYearUnix:function(){

  18.  var date = new Date();

  19.  date.setMonth(0);

  20.  date.setDate(1);

  21.  date.setHours(0);

  22.  date.setMinutes(0);

  23.  date.setSeconds(0);

  24.  date.setMilliseconds(0);

  25.  return date.getTime();

  26.  },

  27.  //获取标准年月日

  28.  getLastDate:function(time){

  29.  var date = new Date(time);

  30.  var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;

  31.  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();

  32.  return date.getFullYear() + '-' + month + '-' + day;

  33.  },

  34.  //转换时间

  35.  getFormatTime:function(timestamp){

  36.  var now = this.getUnix(); // 当前时间戳

  37.  var today = this.getTodayUnix(); // 今天0点的时间戳

  38.  var year = this.getYearUnix(); // 今年0点的时间戳

  39.  var timer = (now - timestamp) / 1000// 转换为秒级时间戳

  40.  var tip = '';

  41.  if(timer <= 0){

  42.  tip = '刚刚';

  43.  }else if(Math.floor(timer/60) <= 0){

  44.  tip = '刚刚';

  45.  }else if(timer < 3600){

  46.  tip = Math.floor(timer/60) + '分钟前';

  47.  }else if(timer >= 3600 && (timestamp - today >= 0)){

  48.  tip = Math.floor(timer/3600) + '小时前';

  49.  }else if(timer/86400 <= 31){

  50.  tip = Math.ceil(timer/86400) + '天前';

  51.  }else{

  52.  tip = this.getLastDate(timestamp);

  53.  }

  54.  return tip;

  55.  }

  56.  }


当然,如果你对JavaScript的Date类型不太了解,可以先去runoob.com上面了解下。


图片描述

接着说回来,Time.getFormatTime()方法就是自定义指令v-time所需要的,参数为毫秒级时间戳,返回已经整理好的时间格式的字符串。

最后,来看我们如何用Vue自定义一个指令v-time:

 
           
  1. Vue.directive('time',{

  2.  bind:function(el, binding){

  3.  el.innerHTML = Time.getFormatTime(binding.value);

  4.  el.__timeout__ = setInterval(function(){

  5.  el.innerHTML = Time.getFormatTime(binding.value);

  6.  }, 60000)

  7.  },

  8.  unbind:function(el){

  9.  clearInterval(el.__timeout__);

  10.  delete el.__timeout__;

  11.  }

  12. })


在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内解除相关绑定。


前端路漫漫,这是不争的事实。而我想说的是,无论前途多么遥远,我都希望你做一个志在四方的少年





推荐阅读

点击下方图片,即可观看



Vue2.5开发去哪儿网App,达到百度T4水平



     

程序员的梦工厂


让更多热爱互联网的同学来慕课网学习

多年以后,圈子里一批技术牛说:

我在慕课网学习过,这就够了




 
慕课网 更多文章 4 年前端狗,2 年 CTO,一个程序员六年的奋斗史 教师节,老师竟然送你礼物!(9.10日,不限名额!!!) 【慕课网实战课】从0开始双剑合璧Laravel,AngularJS全栈开发知乎 五功大成!慕课网安卓5.0客户端重磅发布! 节后第一天慕女神送你书籍给你助力!——评论区留言就送经典IT书籍!
猜您喜欢 Java多线程编程-(6)-你还在使用wait\/notify实现进程间的通信吗? 来自硅谷媒体的最新大数据报道抢鲜看 从大学到公司,除了编程你还需要具备哪些技能 中间件和微服务,Docker以及原生云架构的关系 用尽洪荒之力,也难说服工程师?你需要掌握这 4 个技巧 | 开源思维