vue 自定义时间转换指令(将时间戳转换为“刚刚“,“xx分钟前“,“xx小时前“,“xx天前“)

引言

在一些社区,比如微博、朋友圈等,发布的动态会有个相对本机时间转换后的相对时间,
如图中波浪线圈出的时间
在这里插入图片描述

一般在服务端的存储时间格式是 Unix 时间戳,比如 2017-01-01 00:00 00 的时间戳是1483200000。前端在拿到数据后,将它转换为可读的时间格式再显示出来。

为了显出实时性,在一些社交类产品中,甚至会实时转换为几秒钟前、几分钟前、几小时前等不同的格式,这样比直接转换为年、月、日、时、分、秒更友好。

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

  • index.html
<body>
  <div id="app">
    <div v-time="timeNow"></div>
    <div v-time="timeBefore"></div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="./time.js"></script>
  <script src="./index.js"></script>
</body>
  • index.js
const vm = new Vue({
  el: '#app',
  data: {
    timeNow:(new Date()).getTime(),
    timeBefore: 1488930695721
  },
  components: {},
  created() {},
  methods: {},
})

timeNow 是当前的时间, timeBefore 是一个写死的时间 2017-03-08

注意:本示例所用的时间都是毫秒级的,如果服务端返回秒级的时间戳,需要乘以1000后再使用

时间转换的逻辑
  • 1分钟以前,显示刚刚
  • 1分钟 - 1小时之间,显示“xx分钟前”
  • 1小时 - 1天之间,显示“xx小时前”
  • 1天 - 1个月(31天)之间,显示“xx天前”

为了使判断逻辑更简单,统一使用时间戳进行大小判断。

在写指令 v-time 之前,需要先写一系列与时间相关的函数,我们声明一个对象 Time ,把它们都封装在里面。

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

  • time.js
const Time = {
  // 获取当前时间戳
  getUnix() {
    const date = new Date();
    return date.getTime();
  },
  // 获取今天0点0分0秒的时间戳
  getTodayUnix() {
    const date = new Date();
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    return date.getTime();
  },
  // 获取今年1月1日0点0分0秒的时间戳
  getYearUnix() {
    const date = new Date();
    date.setMonth(0);
    date.setDate(1);
    date.setHours(0);
    date.setMinutes(0);
    date.setSeconds(0);
    date.setMilliseconds(0);
    return date.getTime();
  },
  // 获取标准年月日
  getLastDate(time) {
    const date = new Date(time);
    const year = date.getFullYear();
    const month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
    const day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
    return year + '-' + month + '-' + day;
  },
  // 转换时间
  getFormatTime(timestamp) {
    const now = this.getUnix(); // 当前时间戳
    const today = this.getTodayUnix(); // 今天0点0分0秒时间戳
    const year = this.getYearUnix(); // 今年1月1日0点0分0秒的时间戳
    const timer = (now - timestamp) / 1000; // 获取传递进来的时间和当前时间的差值,并转换为秒级时间戳
    let tip;
    if(timer < 60 || Math.floor(timer / 60) <= 0) {
      tip = '刚刚'
    } else if(timer < 3600) {
      tip = Math.floor(timer / 60) + '分钟前';
    } else if(timer >= 3600 && (timestamp - today) >= 0) {
      tip = Math.floor(timer / 3600) + '小时前';
    } else if((timer / 86400) <= 31){
      tip = Math.floor(timer / 86400) + '天前';
    } else {
      tip = this.getLastDate(timestamp);
    }
    return tip;
  }
}
全局注册自定义指令v-time
const vm = new Vue({
  el: '#app',
  data: {
    timeNow:(new Date()).getTime(),
    timeBefore: 1488930695721
  },
  components: {},
  // 自定义全局指令v-time
  directives: {
    time:{
      bind(el, binding) {
        el.innerHTML = Time.getFormatTime(binding.value);
        el.__timeout__ = setInterval(function(){
          el.innerHTML = Time.getFormatTime(binding.value);
        }, 60000)
      },
      unbind(el) {
        clearInterval(el.__timeout__);
        delete el.__timeout__;
      },
    }
  },
  created() {},
  methods: {},
})
使用效果
<div v-time="timeNow" style="margin-top:40px;"></div>
<div v-time="1619750026000" style="margin-top:20px;"></div>
<div v-time="1619735626000" style="margin-top:20px;"></div>
<div v-time="1619562826000" style="margin-top:20px;"></div>

在这里插入图片描述

前端进阶精选:点此去

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值