《Vue.js实战》- 开发一个实时时间转换指令 v-time

一 般在服务端的存储时间格式是 Unix 时间 戳,比如 2017-01-01 00:00 : 00 的时间 戳是1483200000 。前端在拿到数据后 , 将它转换为可读的时间格式再显示出来 。 为了显 示 出实时性,在一些社交类产品中,甚至会实时转换为几秒钟前、几分钟前、几小时前等不同的格式,这样比直接转换为年、月、日、时、分、秒更友好。本示例就来实现这样一个自定义指令 v-time , 将表达式传入的时间戳实时转换为相对时间。

练习 1 : 开发一个自定义指令 v-birthday ,接收一个出生日期的时间戳,将它转换为己经出生了 xxx 天 。
练习 2 : 扩展练习 1 的 自定义指令 v-birthday ,将出生了 xxx 天转换为具体年龄,比如 25 岁8 个月 10 天 。

效果图:

文件:index.html index.js time.js birthday.js

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>时间转换指令</title>
</head>
<body>
    <!--在一般情况下, v-cloak 是一个解决初始化慢导致页面闪动的最佳实践-->
    <div id="app" v-cloak>
        <div v-time="timeNow"></div>
        <div v-time="timeBefore"></div>
        <hr>
        <div>出生日期: 2020-05-06</div>
        <div v-birthday="birthdayVal"></div>
    </div>
    <script src="../../vue.min.js"></script>
    <script src="time.js"></script>
    <script src="birthday.js"></script>
    <script src="index.js"></script>
</body>
</html>

index.js

let app = new Vue({
    el: "#app",
    //毫秒 服务端返回秒级时问戳需要乘以1000后再使用
    data() {
        return {
            timeNow: (new Date()).getTime(),
            timeBefore: 1488930695721,
            birthdayVal: "2020-05-06"
        }
    },
})

time.js

/* 
 * 1分钟以前,显示“刚刚”。
 * 1 分钟~ 1 小时之间,显示“xx 分钟前”.
 * 1 小时~ 1天之间,显示“xx 小时前”.
 * 1 天~ 1 个月 01 天)之间,显示“xx 天前 ” .
 * 大于 1 个月,显示“xx 年 xx 月 xx 曰’\ 
*/
let time = {
    //获取当前时间戳
    getUnix: function(){
        let date = new Date();
        return date.getTime();
    },
    //获取今天0点0分0秒的时间戳
    getTodayUnix: function(){
        let date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    },
    //获取今年1月1日0点0分0秒的时间戳
    getYearUnix: function(){
        let 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: function(time){
        let date = new Date(time);
        let month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1): date.getMonth() + 1;
        let day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
        return date.getFullYear() + "-" + month + "-" + day;
    },
    // 转换时间
    getFormatTime: function(timestamp){
        let now = this.getUnix(); //当前时间戳
        let today = this.getTodayUnix(); //今天 0 点时间戳
        let year = this.getYearUnix(); //今年 0 点时间戳

        let timer = (now-timestamp) / 1000; //转换为秒级时 间戳
        let tips = "";
        if(timer <= 0 ){
            tips = "刚刚";
        }else if(Math.floor(timer/60) <= 0){
            tips = "刚刚";
        }else if(timer < 3600){
            tips = Math.floor(timer/60) + "分钟前";
        }else if(timer >= 3600 && timestamp - today >= 0){
            tips = Math.floor(timer/3600) + "小时前";
        }else if(timer/86400 <= 31){
            tips = Math.ceil(timer/84600) + "天前";
        }else{
            tips = this.getLastDate(timestamp);
        }
        return tips;
    }
}

Vue.directive("time", {
    bind: function(el, binding){
        el.innerHTML = time.getFormatTime(binding.value);
        el._timeout_  = setInterval(function(){
            el.innerHTML = time.getFormatTime(binding.value);
        }, 60000);
    },
    unbind: function(el){
        clearInterval(el._timeout_);
        delete el._timeout_;
    }
})

birthday.js

let data = {
    getFormatTime: function (dateTemp) {
        let flag = [1, 3, 5, 7, 8, 10, 12, 4, 6, 9, 11, 2];
        
        let start = new Date(dateTemp);
        let end = new Date();

        let year = end.getFullYear() - start.getFullYear();
        let month = end.getMonth() - start.getMonth();
        let day = end.getDate() - start.getDate();
        if (month < 0) {
            year--;
            month = end.getMonth() + (12 - start.getMonth());
        }
        if (day < 0) {
            month--;
            let index = flag.findIndex((temp) => {
                return temp === start.getMonth() + 1
            });
            let monthLength;
            if (index <= 6) {
                monthLength = 31;
            } else if (index > 6 && index <= 10) {
                monthLength = 30;
            } else {
                monthLength = 28;
            }
            day = end.getDate() + (monthLength - start.getDate());
        }
        return year + "岁" + month + "个月"+ day + "天"
    }
}

Vue.directive("birthday", {
    bind: function (el, binding) {
        el.innerHTML = data.getFormatTime(binding.value);
        el._timeout_ = setInterval(function () {
            el.innerHTML = data.getFormatTime(binding.value);
        }, 1000 * 60 * 60 * 24);
    },
    unbind: function (el) {
        clearInterval(el._timeout_);
        delete el._timeout_;
    }
})

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值