浅谈在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入门学习资料收集整理篇
Jul 06 Javascript
Javascript模块化编程(三)require.js的用法及功能介绍
Jan 17 Javascript
纯js简单日历实现代码
Oct 05 Javascript
原生JS实现加入收藏夹的代码
Oct 24 Javascript
js 验证身份证信息有效性
Mar 28 Javascript
JQuery中上下文选择器实现方法
May 18 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
Feb 26 Javascript
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
Jun 17 Javascript
vue实现列表的添加点击
Dec 29 Javascript
vue2.0 常用的 UI 库实例讲解
Dec 12 Javascript
vue中音频wavesurfer.js的使用方法
Feb 20 Vue.js
JS class语法糖的深入剖析
Jul 07 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强制运行广告的方法
2014/12/01 PHP
ThinkPHP实现递归无级分类――代码少
2015/07/29 PHP
利用PHPExcel实现Excel文件的写入和读取
2017/04/26 PHP
jQuery 改变CSS样式基础代码
2010/02/11 Javascript
JavaScript 注册事件代码
2011/01/27 Javascript
jQuery基础框架浅入剖析
2012/12/27 Javascript
用javascript将数据导入Excel示例代码
2014/09/10 Javascript
jQuery实现图片向左向右切换效果的简单实例
2016/05/18 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
微信小程序 教程之注册页面
2016/10/17 Javascript
AngularJS前端页面操作之用户修改密码功能示例
2017/03/27 Javascript
vuejs父子组件之间数据交互详解
2017/08/09 Javascript
Vue一次性简洁明了引入所有公共组件的方法
2018/11/28 Javascript
vue监听浏览器原生返回按钮,进行路由转跳操作
2020/09/09 Javascript
js实现删除json中指定的元素
2020/09/22 Javascript
在vue中动态修改css其中一个属性值操作
2020/12/07 Vue.js
Python实现的监测服务器硬盘使用率脚本分享
2014/11/07 Python
Python的SQLalchemy模块连接与操作MySQL的基础示例
2016/07/11 Python
用Python写脚本,实现完全备份和增量备份的示例
2018/04/29 Python
python调用xlsxwriter创建xlsx的方法
2018/05/03 Python
Python采集代理ip并判断是否可用和定时更新的方法
2018/05/07 Python
django 删除数据库表后重新同步的方法
2018/05/27 Python
python实现文件批量编码转换及注意事项
2019/10/14 Python
Python的几种主动结束程序方式
2019/11/22 Python
python垃圾回收机制(GC)原理解析
2019/12/30 Python
基于Python3.7.1无法导入Numpy的解决方式
2020/03/09 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
2020/04/07 Python
.img/.hdr格式转.nii格式的操作
2020/07/01 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
加拿大奢华时装品牌:Mackage
2018/01/10 全球购物
Linux文件系统类型
2012/09/16 面试题
Unix控制后台进程都有哪些进程
2016/09/22 面试题
啤酒销售实习自我鉴定
2013/09/24 职场文书
JS + HTML 罗盘式时钟的实现
2021/05/21 Javascript
python代码实现备忘录案例讲解
2021/07/26 Python
css3手动实现pc端横向滚动
2022/06/21 HTML / CSS