基于vue3.0+TypeScript的简易日历
2020/4/29 11:32:37
本文主要是介绍基于vue3.0+TypeScript的简易日历,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
第一次用vue3的api和ts写,还在摸索中,有地方写的不规范的,可交流,共同进步
项目介绍,功能很简单
- 显示所有时间日期
- 上一年上个月,下个月下一年
预览地址
arhebin.gitee.io/vue-calenda…
写完后的感受和收获
- ts很香,但我用的不熟练;我平时会看看
vue-next
的源码,既能学新api还能学ts,一举两得呢;当然其他优质代码也可以 - vue3.0新的api很强大;例如就是
reative, ref, watcher, watchEffect...
,选择太多了,给开发者的组合方式也就多了,现在最缺的应该是最佳实践了。 - 最大感受就是之前基于组件的分离,现在还可以基于数据或者方法层面上的抽离,例如我试着写了一个
useComputedDay
和useReducerDate
,有点意思
怎么写日历
我的思路是:
- 需要一个输入的日期,默认是当前日期;这个值可以是传入的
props
,也可以是state
组件自身的状态,(看你喜欢) - 需要知道基于当前日期的年份
- 需要知道基于当前日期的月份
- 需要知道基于当前日期的几号
- 需要知道基于当前日期的当月最大天数
- 需要知道基于当前日期的上一个月最大天数
- 需要知道基于当前日期的当月一号是星期几
这些值都是基于当前日期的,所以大家会想到可以用一个computed
来关联起来,反正我这么想了,😄
有了这些值做什么能?
- 我先画一个7*6的大方块,默认索引是0-41
- 我知道当前日期一号是星期几,就能和上面的索引关联起来,在往后填日子,填到什么时候,就是当月最大天数的量,剩下的就是下一个月的1号还是到索引结束,
- 同理头部,当前日期一号是星期几,之前的可以根据上一月最大天数与索引关联起来,填上去
举个例子🌰
- 今天是2020/4/28;星期2;4月1号是星期三;最大天数是30天;上一个月的最大天数是31天;索引是
index
- 4月份的所有日子1-30怎么填入里格子中呢?当
index - 3 >= 0
就往小格子里填入index - 3 + 1
;直到(30 + 3 - 1) < index
时,😯;剩余头尾 - 尾部触发条件就是
(30 + 3 - 1) < index
,填入index - (30 + 3 - 1)
- 剩下就是头部了,只要填入
31 - (3 - index - 1)
代码如下
<p class="item" v-for="(el, index) in maxDays" :key="index"> <span :class="['day', el.isActive ? 'isactive' : '']" v-if="(index - state.currentMonthFirstDay) >= 0 && (state.currentMonthMaxDays + state.currentMonthFirstDay - 1) >= index"> {{index - state.currentMonthFirstDay + 1}} </span> <span class="day rest " v-else-if="(state.currentMonthMaxDays + state.currentMonthFirstDay - 1) < index">{{index - (state.currentMonthMaxDays + state.currentMonthFirstDay - 1)}}</span> <span class="day rest" v-else>{{state.preMonthMaxDays - (state.currentMonthFirstDay - index - 1)}}</span> </p> 复制代码
剩下的就是上一年上个月,下一年下个月
我的思路是写一个dispatch
,靠action
的type去控制,只要改变当然输入日期就行了。因为依赖已经关联了;(可能一开始会写个最简单一个方法,if-else
的判断)
这些都不是重点啦,大家都有自己的思路。但是重点是包括我在内想知道是怎么基于新api写功能
剩下就是怎么写了
盲写,先实现功能再说
<template> //html结构 </template> <script> step() { const nowDay = new Date().toLocaleDateString().split('/').map(Number) const dayStr = ref<number[]>(nowDay) //这边写成数组,之前是字符串,但写字符串有个问题就是年月日改变一个就会触发所以依赖;数组可以单纯改变一个 //接来利用computed //形成依赖 const date = computed(() => new Date(str.value.join('/'))) //年 const currentYear = computed(() => date.value.getFullYear()) //剩余的值例如currentMonthMaxDays,preMonthMaxDays,currentMonthFirstDay ... //handleChange改变日期的方法 const handleChange = () => { if () { //上一年 } else if() { //上个月 } else if() { //下个月 } else if () { //下一年 } } } </script> 复制代码
当你写完,你会感觉🐸,好长啊。就我个人而言,不怎么喜欢在组件的入口把代码的篇幅搞得很长。
怎么优化呢?
现在基于vue3.0,个人感觉数据,方法也能抽离,除了️组件抽离(只是我个人的想法,可以交流)
- 第一个想法💡是:能不能把基于输入日期的值拿出来溜溜呢? 对于那写当前年份,当前月份等,数据可以抽离成到一个文件中,取个好听的名字叫做
useComputedDay
export const useComputedDay = (str: Ref<number[]>) => { //注入了依赖 const date = computed(() => new Date(str.value.join('/'))) //年 const currentYear = computed(() => date.value.getFullYear()) //月 const currentMonth = computed(() => date.value.getMonth() + 1) //日 const currentDate = computed(() => date.value.getDate()) //星期 const currentDay = computed(() => date.value.getDay()) //当月最大天数 const currentMonthMaxDays = computed(() => getMonthMaxDays(currentYear.value, currentMonth.value)) //当月星期几 const currentMonthFirstDay = computed(() => computedFirstDay(currentYear.value, currentMonth.value)) //上一个月最大天数 // const preMonthMaxDays = computed(() => new Date(currentYear.value, currentMonth.value - 1, 0).getDate()) const preMonthMaxDays = computed(() => getMonthMaxDays(currentYear.value, currentMonth.value - 1)) return { date, currentYear, currentMonth, currentDate, currentDay, currentMonthMaxDays, preMonthMaxDays, currentMonthFirstDay } } 复制代码
怎么用呢?
const nowDay = new Date().toLocaleDateString().split('/').map(Number) const dayStr = ref<number[]>(nowDay) //这边写成数组,之前是字符串,但写字符串有个问题就是年月日改变一个就会触发所以依赖;数组可以单纯改变一个 const dispatch = useReducerDate(dayStr) const { date, currentYear, currentMonth, currentDate, currentDay, currentMonthMaxDays, preMonthMaxDays, currentMonthFirstDay } = useComputedDay(dayStr); 复制代码
这样的话只要dayStr
改变了所有的都会改变
- 第二个想法💡是:能不能把控制上下年月的方法也搞到外面去呢?,例如整个
dispatch
,dispatch
怎么写呢?可以抽离出来写成类似reducer
那样
export const useReducerDate = (state: Ref<number[]>) => { return function (action: action) { switch(action.type) { case 'preYear': { const _var = state.value.map(Number) _var[0] = _var[0] - 1; state.value = _var break; } case 'preMonth': { cutMonth(state); break; } case 'nextYear': { const _var = state.value.map(Number) _var[0] = _var[0] + 1; state.value = _var break; } case 'nextMonth': { addMonth(state); break; } default: { state.value = new Date().toLocaleDateString().split('/').map(Number) } } } } 复制代码
怎么用呢?
<div class="textheader"> <i class="iconfont textItem" @click="dispatch({type: 'preYear'})"></i> <i class="iconfont textItem" @click="dispatch({type: 'preMonth'})"></i> <p class="textItem"> {{state.currentYear}} 年 {{state.currentMonth}} 月 {{state.currentDate}} 日 </p> <i class="iconfont textItem " @click="dispatch({type: 'nextMonth'})"></i> <i class="iconfont textItem" @click="dispatch({type: 'nextYear'})"></i> </div> const dispatch = useReducerDate(dayStr) 复制代码
很简单吧,香不香。
- 主要功能就完成了
源码
github.com/coolpail/vu…
总结
- 主要体会并不是日历怎么实现,而是在vue3.0的背景下,如何更好的基于新的api去实现功能,布局自己的目录结构;api太多了,玩法组合太多了
- 期待大家的写法和想法💡,对交流学习共同进步
这篇关于基于vue3.0+TypeScript的简易日历的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南