浅谈在Vue.js中如何实现时间转换指令


Posted in Javascript onJanuary 06, 2019

在社区中,发布的动态信息,经常会有一个相对余实际发布时间的相对时间。比如这里的微博:

浅谈在Vue.js中如何实现时间转换指令

服务端存储的时间格式,一般为 Unix 时间戳,比如 2019/1/6 13:40:1 的Unix 时间戳为 1546753201651。前端在获取到这个时间戳之后,会转换为可读格式的时间。在社交类产品中,一般会将时间戳转换为 x 分钟前,x 小时前或者 x 天前,因为这样的显示方式用户体验更好。

我们可以自定义一个 v-relative-time 指令来实现上述功能。

html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style type="text/css">

  </style>
</head>
<body>

  <div id="app" v-cloak>
    现在时间:<div v-relative-time="now"></div><p></p>
    2019/1/6 13:45:02:<div v-relative-time="1546753502000"></div><p></p>
    2019/1/6 8:02:02:<div v-relative-time="1546732922000"></div><p></p>
    2019/1/5 22:02:02:<div v-relative-time="before"></div><p></p>
    2019/1/1 22:02:02:<div v-relative-time="1546351322000"></div><p></p>
    2018/1/6 8:02:02:<div v-relative-time="1515196922000"></div>
  </div>


<script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
<script src="index.js"></script>
</body>
</html>

注意:div v-relative-time 指令的入参为精确到毫秒的 Unix 时间戳,如果入参单位为秒,那么可以乘以 1000 后,再传入。

js:

/**
 * 时间对象
 * @type {{getCurrentUnix: Time.getCurrentUnix, getTodayUnix: Time.getTodayUnix, getThisYearUnix: Time.getThisYearUnix, format: Time.format, compensateZero: Time.compensateZero, transform: Time.transform}}
 */
var Time = {
  //获取当前 Unix 时间戳
  getCurrentUnix: function () {
    return new Date().getTime();
  },
  //获取今日 0 点 0 分 0 秒的 Unix 时间戳
  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 秒的 Unix 时间戳
  getThisYearUnix: 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();
  },
  //格式化日期;输出格式为 xxxx-xx-xx
  format: function (val) {
    var dateObj = new Date(val);
    //month 代表月份的整数值从0(1月)到11(12月),所以需要转换
    var month = this.compensateZero(dateObj.getMonth() + 1);
    var day = this.compensateZero(dateObj.getDate());
    return dateObj.getFullYear() + '-' + month + '-' + day;
  },
  /**
   * 如果值小于 10,那么在前面补一个零
   * @param val
   * @returns {*}
   */
  compensateZero: function (val) {
    if (typeof val == 'number') {
      return val < 10 ? '0' + val : val;
    } else {
      return val;
    }
  },
  /**
   * 转换为相对时间
   *
   * 1 分钟之前,返回“刚刚”
   * 1 分钟到 1 小时之间,返回“xx 分钟前”
   * 1 小时到 1 天之间,返回“xx 小时前”
   * 1 天到 1 个月(假设固定为 31 天)之间,返回“xx 天前”
   * 大于 1 个月,返回“xx 年 xx 月 xx 日”
   * @param val unix 时间戳
   */
  transform: function (val) {
    //计算时间间隔(单位:s)
    console.log("getCurrentUnix:" + this.getCurrentUnix());
    var interval = (this.getCurrentUnix() - val) / 1000;

    if (Math.floor(interval / 60) <= 0) {//1 分钟之前
      return '刚刚';
    } else if (interval < 3600) {//1 分钟到 1 小时之间
      return Math.floor(interval / 60) + ' 分钟前';
    } else if (interval >= 3600 && (val - this.getTodayUnix() >= 0)) {//1 小时到 1 天之间
      return Math.floor(interval / 3600) + ' 小时前';
    } else if (interval / (3600 * 24) <= 31) {//1 天到 1 个月(假设固定为 31 天)之间
      return Math.ceil(interval / (3600 * 24)) + ' 天前';
    } else {
      return this.format(val);
    }
  }

};

时间转换逻辑为:

  1. 如果是 1 分钟之前,返回“刚刚”
  2. 如果是 1 分钟到 1 小时之间,返回“xx 分钟前”
  3. 如果是 1 小时到 1 天之间,返回“xx 小时前”
  4. 如果是 1 天到 1 个月(假设固定为 31 天)之间,返回“xx 天前”
  5. 如果是大于 1 个月,返回“xx 年 xx 月 xx 日”

我们专门设计了一个 Time 对象,用于定义与时间相关的函数:

  1. 获取当前 Unix 时间戳。
  2. 获取今日 0 点 0 分 0 秒的 Unix 时间戳。
  3. 获取今年 1 月 1 日 0 点 0 分 0 秒的 Unix 时间戳。
  4. 格式化日期函数,输出格式为 xxxx-xx-xx。
  5. 如果值小于 10,那么在前面补一个零的格式化函数。
  6. 转换为相对时间。

以下是与时间相关的小知识:

Math.floor()
Math.ceil()
/**
 * 相对时间指令
 */
Vue.directive('relative-time', {
  bind: function (el, binding) {
    el.innerHTML = Time.transform(binding.value);
    el._relativeTime = setInterval(function () {
      el.innerHTML = Time.transform(binding.value);
    }, 60000);//每分钟,刷新一次
  },
  unbind: function (el) {
    clearInterval(el._relativeTime);
    delete el._relativeTime;
  }
});

var app = new Vue({
  el: '#app',
  data: {
    now: (new Date()).getTime(),
    //2019/1/5 22:02:02
    before: 1546696922000
  }
});

在相对时间指令中,我们在 bind() 中,把指令中的入参转换为相对时间,然后写入指令所在的元素中,接着还定义了一个每分钟更新元素内容的定时器。在 unbind() 中,执行清除定时器操作。

渲染结果:

浅谈在Vue.js中如何实现时间转换指令

编写自定义指令,建议如下:

  1. 在 bind() 中定义初始化操作,比如绑定一次性事件。
  2. 在 unbind() 中定义解绑与删除操作。
  3. 虽然可以在自定义指令中任意操作 DOM,但这就不是数据驱动 DOM 啦,所以遇到这样的场景,建议使用组件来满足业务要求。

本文示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS两种定义方式的区别、内部原理
Nov 21 Javascript
JS动态添加与删除select中的Option对象(示例代码)
Dec 20 Javascript
jquery 实现两Select 标签项互调示例代码
Sep 25 Javascript
JavaScript保存并运算页面中数字类型变量的写法
Jul 06 Javascript
微信小程序 wxapp内容组件 text详细介绍
Oct 31 Javascript
js实现canvas图片与img图片的相互转换的示例
Aug 31 Javascript
基于Cookie常用操作以及属性介绍
Sep 07 Javascript
Node.js使用MySQL连接池的方法实例
Feb 11 Javascript
vue实现跨域的方法分析
May 21 Javascript
解决layui的form里的元素进行动态生成,验证失效的问题
Sep 14 Javascript
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
Aug 10 Javascript
JavaScript中跨域问题的深入理解
Mar 04 Javascript
浅谈Vue.js中如何实现自定义下拉菜单指令
Jan 06 #Javascript
react-router4按需加载(踩坑填坑)
Jan 06 #Javascript
React 实现拖拽功能的示例代码
Jan 06 #Javascript
Next.js实现react服务器端渲染的方法示例
Jan 06 #Javascript
vue.js引入外部CSS样式和外部JS文件的方法
Jan 06 #Javascript
Bootstrap4 gulp 配置详解
Jan 06 #Javascript
jQuery实现获取当前鼠标位置并输出功能示例
Jan 05 #jQuery
You might like
PHP 类商品秒杀计时实现代码
2010/05/05 PHP
snoopy 强大的PHP采集类使用实例代码
2010/12/09 PHP
PHP类与对象中的private访问控制的疑问
2012/11/01 PHP
PHP针对常规模板引擎中与CSS/JSON冲突的解决方法
2014/08/19 PHP
php实现遍历文件夹的方法汇总
2017/03/02 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
JS中setTimeout()的用法详解
2013/04/14 Javascript
JS实现点击链接取消跳转效果的方法
2014/01/24 Javascript
Node.js静态文件服务器改进版
2016/01/10 Javascript
vue插件tab选项卡使用小结
2016/10/27 Javascript
jquery hover 不停闪动问题的解决方法(亦为stop()的使用)
2017/02/10 Javascript
vue-cli3 配置开发与测试环境详解
2019/05/17 Javascript
ES6 Symbol数据类型的应用实例分析
2019/06/26 Javascript
vue router总结 $router和$route及router与 router与route区别
2019/07/05 Javascript
vuex存储token示例
2019/11/11 Javascript
解决Can't find variable: SockJS vue项目的问题
2020/09/22 Javascript
解析Python中的__getitem__专有方法
2016/06/27 Python
Python搭建HTTP服务器和FTP服务器
2017/03/09 Python
Django 生成登陆验证码代码分享
2017/12/12 Python
pytorch中tensor的合并与截取方法
2018/07/26 Python
python可视化实现代码
2019/01/15 Python
Python流行ORM框架sqlalchemy安装与使用教程
2019/06/04 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
Python yield生成器和return对比代码实例
2020/04/20 Python
无谷物狗粮:Pooch & Mutt
2018/05/23 全球购物
Hudson Jeans官网:高级精制牛仔裤
2018/11/28 全球购物
马来西亚在线健康商店:Medipal Malaysia
2020/04/13 全球购物
如何获取某个日期是当月的最后一天
2013/12/05 面试题
2014年班主任自我评价范文
2014/04/23 职场文书
追悼会悼词大全
2015/06/23 职场文书
2019年二手房买卖合同范本
2019/10/14 职场文书
Html5调用企业微信的实现
2021/04/16 HTML / CSS
聊聊pytorch测试的时候为何要加上model.eval()
2021/05/23 Python
MySQL千万级数据表的优化实战记录
2021/08/04 MySQL
Java 写一个简单的图书管理系统
2022/04/26 Java/Android