浅谈在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 相关文章推荐
如何确保JavaScript的执行顺序 之jQuery.html并非万能钥匙
Mar 03 Javascript
页面回到顶部的三种实现(锚标记,js)
Oct 01 Javascript
javascript中AJAX用法实例分析
Jan 30 Javascript
在IE8上JS实现combobox支持拼音检索功能
May 23 Javascript
jQuery Validate插件实现表单验证
Aug 19 Javascript
纯js实现画一棵树的示例
Sep 05 Javascript
JS基于递归实现网页版计算器的方法分析
Dec 20 Javascript
使用百度地图实现地图网格的示例
Feb 06 Javascript
Vue封装Swiper实现图片轮播效果
Feb 06 Javascript
解决Mac node版本升级失败的问题
May 16 Javascript
uploadify插件实现多个图片上传并预览
Sep 30 Javascript
VUE中的v-if与v-show区别介绍
Mar 13 Vue.js
浅谈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静态新闻列表自动生成代码
2007/06/14 PHP
PHP 抓取网页图片并且另存为的实现代码
2010/03/24 PHP
php curl 模拟登录并获取数据实例详解
2016/12/22 PHP
php实现的pdo公共类定义与用法示例
2017/07/19 PHP
PHP实现的迪科斯彻(Dijkstra)最短路径算法实例
2017/09/16 PHP
php取出数组单个值的方法
2018/03/12 PHP
使用新的消息弹出框blackbirdjs
2008/10/16 Javascript
多浏览器兼容的获取元素和鼠标的位置的js代码
2009/12/15 Javascript
js限制textarea每行输入字符串长度的代码
2012/10/31 Javascript
纯JS实现根据CSS的class选择DOM
2014/03/22 Javascript
JQuery select(下拉框)操作方法汇总
2015/04/15 Javascript
关于JavaScript数组你所不知道的3件事
2016/08/24 Javascript
js字符串引用的两种方式(必看)
2016/09/18 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
Angular ui.bootstrap.pagination分页
2017/01/20 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
webpack打包nodejs项目的方法
2018/09/26 NodeJs
vue中v-for循环给标签属性赋值的方法
2018/10/18 Javascript
vue中node_modules中第三方模块的修改使用详解
2019/05/31 Javascript
[08:53]DOTA2每周TOP10 精彩击杀集锦vol.9
2014/06/26 DOTA
[03:04]2018年国际邀请赛典藏宝瓶&莱恩声望物品展示 片尾有彩蛋
2018/06/04 DOTA
python实现简单的计时器功能函数
2015/03/14 Python
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
Python实现文件信息进行合并实例代码
2018/01/17 Python
python机器人行走步数问题的解决
2018/01/29 Python
python实现数独游戏 java简单实现数独游戏
2018/03/30 Python
详解pyenv下使用python matplotlib模块的问题解决
2018/11/29 Python
new修饰符是起什么作用
2015/06/28 面试题
中学老师的自我评价
2013/11/07 职场文书
小学毕业典礼主持词
2014/03/27 职场文书
借款担保书范文
2014/05/13 职场文书
社区四风存在问题及整改措施
2014/10/26 职场文书
2015年质量管理工作总结范文
2015/05/18 职场文书
2015年企业员工工作总结范文
2015/05/21 职场文书
2016父亲节感恩话语
2015/12/09 职场文书
如何使用PyCharm及常用配置详解
2021/06/03 Python