vue3实现封装时间计算-日期倒计时组件-还有XX天&第XX天
vue3封装时间计算-日期倒计时组件——还有XX天 & 第XX天 & 年月日时分秒星期几方法的封装 & setup语法糖完整用法之reactive, ref, onMounted,computed
效果
1-还有几天
2-第几天
需求
依照服务端返回的日期与当前日期进行对比
- 1、返回日期大于当前日期为 “还有XX天”
- 2、返回日期小于当前日期为 “第XX天”
代码
1、倒计时组件封装
1.1、时间原则计算组件
src/components/header/countDown.vue
<script lang="ts" setup> import { ref } from 'vue' const days = ref(3) const condition = ref('还有/第') const text = ref(`距2021-2022年迎峰度冬安全生产值班${condition.value}${days.value}天`) </script> <template> <div class="days"> <!--1.0、封装 --> {{ text }} </div> </template> <style scoped> .days { color: #FFFFFF; font-size: 20px; position: relative; left: 20px; top: 50px; width: 600px; } </style>
1.2、时间展示组件
效果-大屏右上角展示时间
src/components/header/date.vue
<template> <div>{{ date }}</div> </template> <script lang="ts" setup> import formatter from '@/utils/formatterData' import { ref, onMounted } from 'vue' const date = ref('') onMounted(() => { setInterval(() => { getDate() }, 1000) }) const getDate = function () { date.value = formatter(new Date()) } </script> <style scoped lang="scss"> </style>
1.3、时间公共方法封装-中文格式
XXXX年XX月XX日XX时XX分XX秒 星期X
src/utils/formatterData.ts
const complement = function (value:any) { return value < 10 ? `0${value}` : value } export default (date:any) => { const time = new Date(date) const year = time.getFullYear() const month = complement(time.getMonth() + 1) const day = complement(time.getDate()) const hour = complement(time.getHours()) const minute = complement(time.getMinutes()) const second = complement(time.getSeconds()) const week = '星期' + '日一二三四五六'.charAt(time.getDay()) return `${year}年-${month}-月${day}日 ${week} ${hour}:${minute}:${second}` }
1.4、时间公共方法封装-数字格式
XXXX年XX月XX日XX时XX分XX秒 【数字格式】
src/utils/date.ts
/* * @Author: CL * @Date: 2021-10-21 14:09:07 * @LastEditTime: 2021-10-21 16:28:55 * 工具方法 */ export const formatTime = (data: Date | string, flag: boolean) => { const date = new Date(data) const y = date.getFullYear() let m: number | string = date.getMonth() + 1 m = m < 10 ? ('0' + m) : m let d : number | string = date.getDate() d = d < 10 ? ('0' + d) : d let h : number | string = date.getHours() h = h < 10 ? ('0' + h) : h let minute : number | string = date.getMinutes() minute = minute < 10 ? ('0' + minute) : minute let second: number | string = date.getSeconds() second = second < 10 ? ('0' + second) : second if (flag) { return y + '-' + m + '-' + d } return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second }
2、页面引用
效果-倒计时完整版
index.vue
<script setup lang="ts"> import { reactive, ref, computed, onMounted } from 'vue' import { getPowerProgress, getMatchByDate } from '@/api/olympicWinter/left/Match_Schedule.ts' // 2.0、引用 import countDown from '@/components/header/countDown.vue' import date from '@/components/header/date.vue' import { formatTime } from '@/utils/utils' // 生成 0-n的数字 const indexMethod = (index: any) => { return index + 1 } // interface propType { // type: string // } // const props = defineProps<propType>() const props = { type: '01' } // 时间列表数据 const listData = reactive([ { time: '02', today: '周三', date: '2022-02-02' }, { time: '03', today: '周四', date: '2022-02-03' } ]) const lists = reactive([ { id: '', lineName: '', toStation: '' } ]) // 滑动的元素 const scrollcontent = ref() const totleactive = ref(0) // interface 描述一个对象或者函数 interface matchInfo { competitionDate: string competitionEvent: string } const matchList = ref<Array<matchInfo>>([]) /** * 根据日期得到结果 */ const getMatch = async (date: string) => { const res = await getMatchByDate(date) matchList.value = res } /** * 点击某个日期触发 */ const totleMethod = (data: any, index: number) => { totleactive.value = index getMatch(data.date) } /** * 获取接口数据 */ const getProgress = async () => { const time = new Date() const nowTime = formatTime(time, true) const res = await getPowerProgress(nowTime) console.log(res, 'kkkk') const temp = listData.filter((item: any) => { return item.date === nowTime }) if (temp.length <= 0) { // 不在期限里, 就取数组的第一个 getMatch(listData[0].date) } else { getMatch(nowTime) } } onMounted(() => { getProgress() }) const textType = computed(() => { let text = '' if (props.type === '01') { text = '线路名称' } else if (props.type === '02') { text = '变电站名称' } else if (props.type === '03') { text = '用户名称' } return text }) </script>
<template> <div class="main-container"> <div class="head-container"> <div class="head-content"> <!--3.0、使用 --> <countDown /> <div class="left" /> <div class="main"> <div class="left" /> <div class="right"> <date /> </div> </div> </div> <div class="count"> <!-- 3.1、ref和interface 定义变量的用法 --> <div v-for="(item, index) in matchList" :key="index" > <span>{{ item.competitionDate }}</span> <span>{{ item.competitionEvent }}</span> </div> <!-- 3.2、reactive 定义变量的用法 --> <div class="scroll" ref="scrollcontent" > <div :class="[totleactive === index ? 'totleactive' : 'totlebox']" v-for="(item,index) in listData" :key="index" @click="totleMethod(item, index)" > <p>{{ item.time }}</p> <p>{{ item.today }}</p> </div> </div> <!-- 3.3、onMounted 定义变量的用法 --> <div> <span>{{ textType }}</span> </div> <div> <el-table :data="lists"> <el-table-column prop="lineName" label="序号" type="index" align="center" width="80" :index="indexMethod" /> <el-table-column prop="toStation" align="center" :label="textType" /> </el-table> </div> </div> </div> </div> </template>
<style scoped lang="scss"> .main-container { width: 7660px; height: 1070px; display: grid; padding: 0 10px 10px; grid-gap: 0 10px; grid-template-columns: repeat(4, 1fr); grid-template-rows: 120px auto; background-image: url(@/assets/yfdd-bs/bg.png); background-size: cover; color: #fff; font-size: 23px; grid-template-areas: "a a a a" "b c c d"; .head-container { height: 120px; background-image: url(@/assets/yfdd-bs/title.png); background-repeat: no-repeat; background-size: contain; background-position: center; grid-area: a; display: flex; } .head-content { width: 100%; display: flex; background-repeat: no-repeat; background-size: contain; background-position: center; cursor: pointer; .left { width: 50%; display: flex; justify-content: center; align-items: center; margin-left: -200px; } .main { width: 53%; display: flex; justify-content: end; } .left { width: 50%; } .right { display: flex; justify-content: right; line-height: 145px; font-size: 40px; } } //时间样式 .scroll { width: 2000px; display: flex; transition: all 2s; // transform: all 1s; // margin-left: -600px; // justify-content: space-around; .totlebox { // width: 53px; // height: 53px; cursor: pointer; display: flex; flex-direction: column; justify-content: center; align-items: center; margin: 0 29px; padding: 4px; margin-top: 5px; p { font-size: 24px; font-family: PingFangSC; font-weight: bold; color: #ffffff; } p:nth-child(2) { font-size: 16px; } } .totleactive { width: 53px; height: 53px; display: flex; flex-direction: column; justify-content: center; background: #1269c2; border-radius: 50%; align-items: center; margin: 0 29px; padding: 4px; margin-top: 5px; p { font-size: 24px; font-family: PingFangSC; font-weight: bold; color: #ffffff; } p:nth-child(2) { font-size: 16px; } } } } </style>
接口
src/api/olympicWinter/left/Match_Schedule.ts
/** * 根据日期获取接口数据 * date: 日期 */ export const getPowerProgress = (date: string) => { return request({ method: 'GET', url: '/bdDailyInfo/queryBDProgress', params: { competitionDate: date } }) } /** * 根据时间日期获取比赛数据 * date: 日期 */ export const getMatchByDate = (date: string) => { return request({ method: 'POST', url: '/competitionInfo/selectAll', data: { competitionDate: date } }) }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
浅谈vue项目利用Hbuilder打包成APP流程,以及遇到的坑
这篇文章主要介绍了浅谈vue项目利用Hbuilder打包成APP流程,以及遇到的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-09-09
最新评论