小白学VUE——实现抖音时钟(NPM方式)

工具安装:

1.Nodejs:我喜欢用免安装版,自己配置,用的放心(但是更操心,55555~~~~~),这里不多说,如果Nodejs还不会,那还是得先了解一下Nodejs的基本用法(请自行百度)

2.安装Vue及相关:如何安装Vue,如何创建项目也不多说了(仍然自行百度)。另外为了方便,需要SCSS的支持,需要安装scss-loader解析css样式(也可以自己替换成css,省去安装步骤)。

实现效果:

实现原理:

1.设定时钟入口(Timer.vue)

2.设定年(Year.vue)、月(Month.vue)、周(Week.vue)、日(Day.vue)、午时(Apm.vue)、小时(Hour.vue)、分钟(Minute.vue)、秒钟(Second.vue)组件

3.传参,在时钟入口设定一个定时器,每秒钟计算当前时间,将当前时间传递给子组件,更新组件状态,从而实现时钟显示

4.设定时间的显示格式数据,也就是语言库(store.ts)

因此文件目录如下:

实现步骤:

1.新建好所有目录及文件

2.在App.vue中引入Timer.vue,以便查看效果(用的是Vue原装自带Demo,就只加了一个链接)

3.在main.ts中添加store文件夹扫描,方便后面调用相关引用

4.定义Timer组件(将整个时钟定义为一个组件,将组件在App.vue页面中显示),在组件中嵌套时钟子组件(时分秒等组件)

Timer.vue代码如下:

<!--定义时钟组件-->
<template>
    <div id="timer">
        <!--秒钟子组件-->
        <Second :second="second" :secondBox="secondBox" :secondRange="320"></Second>
        <!--分钟子组件-->
        <Minute :minute="minute" :minuteBox="minuteBox" :minuteRange="270"></Minute>
        <!--小时子组件-->
        <Hour :hour="hour" :hourBox="hourBox" :hourRange="220"></Hour>
        <!--午时子组件-->
        <Apm :apm="apm" :apmBox="apmBox" :apmRange="185"></Apm>
        <!--日期子组件-->
        <Day :day="day" :dayBox="dayBox" :dayRange="150"></Day>
        <!--周子组件-->
        <Week :week="week" :weekBox="weekBox" :weekRange="100"></Week>
        <!--月度子组件-->
        <Month :month="month" :monthBox="monthBox" :monthRange="50"></Month>
        <!--年度子组件-->
        <Year :year="year"></Year>
        <!--语言转换开关-->
        <ul style="bottom: -35px;">
            <li>
                <input type="checkbox" id="checkbox" @click="switchFont" style="z-index: 9999999;position: relative;">
            </li>
        </ul>
    </div>
</template>
<script>
//引入各个组件
import Year from '@/components/timer/Year.vue'
import Month from '@/components/timer/Month.vue'
import Week from '@/components/timer/Week.vue'
import Day from '@/components/timer/Day.vue'
import Apm from '@/components/timer/Apm.vue'
import Hour from '@/components/timer/Hour.vue'
import Minute from '@/components/timer/Minute.vue'
import Second from '@/components/timer/Second.vue'
import store from '../store/timer/store.ts'

export default {
    name : 'Timer',
    //引入组件
    components : {
        Year,
        Month,
        Week,
        Day,
        Apm,
        Hour,
        Minute,
        Second
    },
    data() {
        //初始化时间
        return {
            //当前时间
            second : "",
            minute : "",
            hour : "",
            apm : "",
            day : "",
            week : "",
            month : "",
            year : "",
            //周期列表(用于存放对应的语言库)
            secondBox : [],
            minuteBox : [],
            hourBox : [],
            apmBox : [],
            dayBox : [],
            weekBox : [],
            monthBox : [],
            //当月天数(动态获取,根据当月天数要自动计算扇区角度,网络上有很多代码直接写成固定的30天)
            days : 0,
            //字体开关(默认简体中文)
            fontType : "Simplified"
        }
    },
    methods: {
        //定时器启动方法
        start() {
            //初始化语言库,装配语言库(先把底图数据显示出来)
            this.makeDate();
            //获取当前时间(计算当前时间,实时更新)
            setInterval(
                () => {
                    let date = new Date();
                    //组装年份
                    this.year = date.getFullYear();
                    //组装月份
                    this.month = date.getMonth() + 1;
                    //获取当月总天数
                    this.days = new Date(this.year,this.month,0).getDate();
                    //获取当年的天干地支信息
                    this.year = store.sky[this.year % 10] + store.land[this.year % 12];
                    //获取星期几
                    this.week = date.getDay();
                    //获取当天几号
                    this.day = date.getDate();
                    //获取当前小时(12小时制)
                    this.hour = (date.getHours() > 12 ? (date.getHours() -12) : date.getHours());;
                    //获取当前分钟(从0分钟开始,因此分钟需增加1)
                    this.minute = date.getMinutes() + 1;
                    //获取当前秒钟(从0秒钟开始,因此秒钟需增加1)
                    this.second = date.getSeconds() + 1;
                    //获取当前是上午还是下午
                    if(this.hour > 12) {
                        this.apm = 2;
                    }else{
                        this.apm = 1;
                    }
                    //组装数据(更新底图,重新装配,达到时钟转动的效果)
                    this.makeDate();
                }
            , 1000);
        },
        makeDate(){
            //初始化数据
            this.secondBox = [];
            this.minuteBox = [];
            this.hourBox = [];
            this.apmBox = [];
            this.dayBox = [];
            this.weekBox = [];
            this.monthBox = [];
            //获取配置数据
            let fdata = null;
            if(this.fontType == "Simplified"){
                fdata = store.format_Simplified;
            }else{
                fdata = store.format_Traditional;
            }
            //组装月
            for(let i=1 ; i<= 12 ; i++){
                if(i <= 10){
                    this.monthBox.push(fdata[i] + "月");
                }else {
                    this.monthBox.push(fdata[10] + fdata[i % 10] + "月");
                }
            }
            //组装周
            for(let i=1 ; i<= 7 ; i++){
                this.weekBox.push("星期" + fdata[i]);
            }
            //组装日
            for(let i=1 ; i<= this.days ; i++){
                if(i <= 10){
                    this.dayBox.push(fdata[i] + "日");
                }else if(i < 20){
                    this.dayBox.push(fdata[10] + fdata[i % 10] + "日");
                }else{
                    if(i % 10 == 0){
                        this.dayBox.push(fdata[parseInt(i / 10)] + fdata[10] + "日");
                    }else{
                        this.dayBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "日");
                    }
                }
            }
            //组装午时
            this.apmBox.push("上午");
            this.apmBox.push("下午");
            //组装小时
            for(let i=1 ; i<= 12 ; i++){
                if(i <= 10){
                    this.hourBox.push(fdata[i] + "点");
                }else{
                    this.hourBox.push(fdata[10] + fdata[i % 10] + "点");
                }
            }
            //组装分钟
            for(let i=0 ; i< 60 ; i++){
                if(i <= 10){
                    this.minuteBox.push(fdata[i] + "分");
                }else if(i < 20){
                    this.minuteBox.push(fdata[10] + fdata[i % 10] + "分");
                }else{
                    if(i % 10 == 0){
                        this.minuteBox.push(fdata[parseInt(i / 10)] + fdata[10] + "分");
                    }else{
                        this.minuteBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "分");
                    }
                }
            }
            //组装秒
            for(let i=0 ; i< 60 ; i++){
                if(i <= 10){
                    this.secondBox.push(fdata[i] + "秒");
                }else if(i < 20){
                    this.secondBox.push(fdata[10] + fdata[i % 10] + "秒");
                }else{
                    if(i % 10 == 0){
                        this.secondBox.push(fdata[parseInt(i / 10)] + fdata[10] + "秒");
                    }else{
                        this.secondBox.push(fdata[parseInt(i / 10)] + fdata[10] + fdata[i % 10] + "秒");
                    }
                }
            }
        },
        //语言开关,若当前为简体,则转换为繁体,反之亦然
        switchFont(){
            this.fontType = (this.fontType == "Simplified" ? "Traditional" : "Simplified");
        }
    },
    created() {
        //页面加载完成后启动
        this.start();
    }
}
</script>

<style lang="scss">
//时钟样式
#timer {
  ul {
    list-style-type: none;
    padding: 0;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    height: 60px;
    width: 60px;
    transition: 0.1s 0.1s ease-in;
    li {
      position: absolute;
      height: 60px;
      width: 60px;
      color: rgb(204, 46, 46);
      text-align: center;
      font-size: 9px;
      line-height: 60px;
      &.hover {
        text-shadow: #009be5 0px 0px 10px, 
        #98f24e 0px 0px 20px, 
        #0c16d6 0px 0px 30px, 
        #b5e927 0px 0px 40px, 
        #d32cbe 0px 0px 70px, 
        #dc1313 0px 0px 80px, 
        #9a17c0 0px 0px 100px;
      }
    }
  }
}
</style>

5.定义月、周、日、午时、小时、分钟、秒钟组件,代码大同小异(就接收参数不同),这里用月组件来展示

Month.vue

<template>
    <!--将旗下内容按360度等分后并逆时针旋转-->
    <ul :style="{transform:`rotate(${-360 / list.length * (rotates - 1)}deg)`}">
        <!--遍历语言库数据,当前时间采用高亮样式-->
        <li v-for="(item,index) in list" :key="index" 
            :class="{hover: index == rotates - 1}" 
            :style="{transform:`rotate(${360 / list.length * index}deg)  translateX(${range}px)`}">
            {{ item }}
        </li>
    </ul>
</template>
<script>
//使用props接受父组件传递的月度数据,其中包含month、monthBox、monthRange
//其他周、日、天等组件,只是接收的数据不同,监听的数据不同,其他都相同(所有控制都在父组件中)
//注意watch用法,这里有坑
export default {
    name : 'month',
    props : ["month","monthBox","monthRange"],
    data() {
        return {
            rotates : "",
            list : [],
            range : 0
        }
    },
    //添加vue的监听器(watch),对数值变化进行监听,让数据动起来
    watch : {
        month(val) {
            this.rotates = val;
        },
        monthBox(val){
            this.list = val;
        },
        monthRange: {
            handler(val){
                this.range = val;
            },
            immediate : true
        }
    }
}
</script>
<style scoped lang="scss">
//层级样式,不要也行
ul {
    z-index: 2;
}
</style>

这里有人就要问了,为什么这些代码相同,为什么我不写在一起呢,嗯嗯,这是为了满足面向对象开发的要求啊~~~

6.定义年度组件

Year.vue

<template>
    <ul>
        <li>{{yearLabel}}</li>
    </ul>
</template>

<script>
export default {
    name : "year",
    props : ["year"],
    data() {
        return {
            yearLabel : ""
        }
    },
    watch : {
        year(val){
            this.yearLabel = val;
        }
    }
}
</script>

7.我们来看看语言库里是什么样子的

store.ts

export default {
    format_Traditional : ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '拾', '佰', '仟', '万'],
    format_Simplified : ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '百', '千', '万'],
    sky : ['庚', '辛', '壬', '癸', '甲', '乙', '丙', '丁', '戊', '己'],
    land : ['申', '酉', '戌', '亥','子', '丑', '寅', '卯', '辰', '巳', '午', '未']
}

运行看看,原理是不是很简单?

 

代码有参考网络上的某大神开发Demo,原文找不到了,无法当面感谢,原理有借鉴,但代码重整了,若存在侵权请告知删除!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值