浅谈在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最新动画教程+iso光盘下载
Jan 22 Javascript
js用图作提交按钮或超连接
Mar 26 Javascript
JS解密入门之凭直觉解
Jun 25 Javascript
jQuery解决iframe高度自适应代码
Dec 20 Javascript
IE6、IE7中获取Button元素的值的bug说明
Aug 28 Javascript
JS实现简洁、全兼容的拖动层实例
May 13 Javascript
Jquery zTree 树控件异步加载操作
Feb 25 Javascript
实例详解display:none与visible:hidden的区别
Mar 30 Javascript
vue-cli如何快速构建vue项目
Apr 26 Javascript
JavaScript定义函数的三种实现方法
Sep 23 Javascript
vue.js的简单自动求和计算实例
Nov 08 Javascript
Vue3配置axios跨域实现过程解析
Nov 25 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 md5下16位和32位的实现代码
2008/04/09 PHP
PHP 一个比较完善的简单文件上传
2010/03/25 PHP
PHP mysql与mysqli事务使用说明 分享
2013/08/17 PHP
PHP实现抓取Google IP并自动修改hosts文件
2015/02/12 PHP
PHP中file_exists使用中遇到的问题小结
2016/04/05 PHP
php redis实现对200w用户的即时推送
2017/03/04 PHP
让iframe框架网页在任何浏览器下自动伸缩
2006/08/18 Javascript
dropdownlist之间的互相联动实现(显示与隐藏)
2009/11/24 Javascript
Javascript 中 null、NaN和undefined的区别总结
2013/04/10 Javascript
js中prototype用法详细介绍
2013/11/14 Javascript
JavaScript中字符串拼接的基本方法
2015/07/07 Javascript
JAVASCRIPT代码编写俄罗斯方块网页版
2015/11/26 Javascript
js点击返回跳转到指定页面实现过程
2020/08/20 Javascript
JS动态给对象添加事件的简单方法
2016/07/19 Javascript
js判断radiobuttonlist的选中值显示/隐藏其它模块的实现方法
2016/08/25 Javascript
js HTML5上传示例代码完整版
2016/10/10 Javascript
微信小程序 如何引入外部字体库iconfont的图标
2018/01/31 Javascript
Vue2.0用户权限控制解决方案的示例
2018/02/10 Javascript
javascript数据类型中的一些小知识点(推荐)
2019/04/18 Javascript
JavaScript创建、读取和删除cookie
2019/09/03 Javascript
环形加载进度条封装(Vue插件版和原生js版)
2019/12/04 Javascript
[00:12]DAC2018 Miracle-站上中单舞台,他能否再写奇迹?
2018/04/06 DOTA
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[01:38]完美世界DOTA2联赛(PWL)宣传片:第一站
2020/10/26 DOTA
简单的Python2.7编程初学经验总结
2015/04/01 Python
python中assert用法实例分析
2015/04/30 Python
Python网络编程基于多线程实现多用户全双工聊天功能示例
2018/04/10 Python
python GUI库图形界面开发之PyQt5不规则窗口实现与显示GIF动画的详细方法与实例
2020/03/09 Python
Python descriptor(描述符)的实现
2020/11/15 Python
Python控制鼠标键盘代码实例
2020/12/08 Python
CSS3 实现弹幕的示例代码
2017/08/07 HTML / CSS
反腐倡廉剖析材料
2014/09/30 职场文书
爱心捐书倡议书
2015/04/27 职场文书
用人单位聘用意向书
2015/05/11 职场文书
厉害!这是Redis可视化工具最全的横向评测
2021/07/15 Redis
JavaScript ES6的函数拓展
2022/01/18 Javascript