start
- This article purely rely on their own ideas to write, if there are similar, also is not plagiarism.
- Before reading this article, you need to know a bit about TS, VUe3, and JSX syntax. 😯 and moment grammar.
The expected effect or the actual effect is exactly the same 😄
- Envisioned effect Element-UI calendar component
- The actual effect
implementation
- The implementation of calendar component, with the help of moement. Js greatly simplifies the calculation process, but also reduces a lot of code. Can be said to greatly reduce the difficulty of implementation.
- This article is intended as an exercise only. Please correct any errors.
- Calendar this everybody knows, laborious introduce the use of the scene that the personal feel is not useful, you met naturally can think of.
Calculating dates – which dates the page displays – is the primary function
- There are actually two types of this: the one where the page only shows the current month, or the one in the picture above, which shows a week per line, which is a little bit more complicated. Why more complicated?
- To get the whole month, you just get the number of days of the month and then you add them up from the first to get all the days of the month.
- With a weekly one-line display, you need to get the day of the week for the first day of the current month and then calculate how many days forward to show it.
interface obj {
[propName: string]: string | number;
}
// The date of the week is translated into Chinese
const weekList = ['Sunday'.'Monday'.'on Tuesday'.'on Wednesday'.'on Thursday.'on Friday'.'on Saturday]
let listOfDatesOfTheMonth: Array<obj> = reactive([])
// Calculate the number of days the calendar needs to display
const generatedDate = (val? : string) = > {
// Obtain is a few months
const month = moment(val || new Date()).format('YYYY-MM')
// Obtain the day of the week for the first day of the month
const whichDay = moment(month).startOf('month').weekday()
// Calculate the start date from 7 minus the day of the week (0123456, where 0 represents Sunday)
const startDate = moment(moment(month).subtract(7 - whichDay, 'days')).format('YYYY-MM-DD')
// Organize the data
// [...Array(42).keys()] [...Array(42).keys()] Because some of the months are 28 or 30, 31, 35, some of the months are not fully displayed.
listOfDatesOfTheMonth = [...Array(42).keys()].reduce((acc:Array<obj>, val) = > {
// Get the date of presentation
const date = moment(startDate).add(val + 1.'days').format('YYYY-MM-DD')
// The split date is used to get the number such as 123456
const dateList = date.split(The '-')
// Get the day of the week
const week = moment(date).weekday()
// Put the required data into an array
acc.push({ index: val + 1.date: date, day: dateList[dateList.length - 1].week: weekList[week] })
// Return an array to reduce
return acc
}, [])
console.log(listOfDatesOfTheMonth)
getDateItemList()
}
Copy the code
Last month or the same day or the next month
- To implement this, we need to record the current month, and then add a month minus a month, and then just new Date()?
// Current day Selects the day
const currentDate = ref(moment().format('YYYY-MM-DD'))
/ / the current month
const currentMonth = ref(moment().format('YYYY-MM'))
// Last month, next month, current month
const changeMonth = (type: string) = > {
// Set the date. This is used to recreate the display data when clicking on a month other than the current month
if (type === 'setDate') {
currentMonth.value = moment(currentDate.value).format('YYYY-MM')}/ / today
if (type === 'today') {
currentMonth.value = moment().format('YYYY-MM')}/ / next month
if (type === 'nextMonth') {
currentMonth.value = moment(currentMonth.value).add(1.'month').format('YYYY-MM')}/ / last month
if (type === 'lastMonth') {
currentMonth.value = moment(currentMonth.value).subtract(1.'month').format('YYYY-MM')
}
currentDate.value = moment(currentMonth.value).format('YYYY-MM-DD')
generatedDate(currentMonth.value)
}
Copy the code
Click on the calendar date
- This has two effects: one is to add a background color to the selected date and determine if the current date is equal to the selected date and add a class implementation
- Click on a date other than the current month to regenerate the data.
// Set the selected day for the current day
const setCurrentDate = (date:string) = > {
currentDate.value = date
// Regenerate the calendar with different months
if (date.indexOf(currentMonth.value) === -1) {
changeMonth('setDate')}}// Get the daily Settings style and action
let dateItemList: JSX.Element[] = []
const getDateItemList = () = > {
dateItemList = listOfDatesOfTheMonth.map(item= > {
Date can be a string or an array. See obj's definition
const isCurrentMonth = String(item.date).indexOf(currentMonth.value) === -1
// Calculate the bound class
const className = `dateItem ${isCurrentMonth ? ' ' : 'currentMonth'} ${currentDate.value === item.date ? 'currentDate' : ' '}`
return <div onClick={()= > { setCurrentDate(item.date + '') }} class={className}>{parseInt(item.day + '') }</div>})}Copy the code
The final code
import { defineComponent, ref, reactive, onMounted, watch } from 'vue'
import './indenx.scss'
import moment from 'moment'
export default defineComponent({
name: 'calender',
setup () {
interface obj {
[propName: string]: string | number;
}
// Current day Selects the day
const currentDate = ref(moment().format('YYYY-MM-DD'))
/ / the current month
const currentMonth = ref(moment().format('YYYY-MM'))
const weekList = ['Sunday'.'Monday'.'on Tuesday'.'on Wednesday'.'on Thursday.'on Friday'.'on Saturday]
let listOfDatesOfTheMonth: Array<obj> = reactive([])
// Calculate the number of days the calendar needs to display
const generatedDate = (val? : string) = > {
// Obtain is a few months
const month = moment(val || new Date()).format('YYYY-MM')
// Obtain the day of the week for the first day of the month
const whichDay = moment(month).startOf('month').weekday()
// Calculate the start date from 7 minus the day of the week (0123456, where 0 represents Sunday)
const startDate = moment(moment(month).subtract(7 - whichDay, 'days')).format('YYYY-MM-DD')
// Organize the data
// [...Array(42).keys()] [...Array(42).keys()] Because some of the months are 28 or 30, 31, 35, some of the months are not fully displayed.
listOfDatesOfTheMonth = [...Array(42).keys()].reduce((acc:Array<obj>, val) = > {
// Get the date of presentation
const date = moment(startDate).add(val + 1.'days').format('YYYY-MM-DD')
// The split date is used to get the number such as 123456
const dateList = date.split(The '-')
// Get the day of the week
const week = moment(date).weekday()
// Put the required data into an array
acc.push({ index: val + 1.date: date, day: dateList[dateList.length - 1].week: weekList[week] })
// Return an array to reduce
return acc
}, [])
console.log(listOfDatesOfTheMonth)
getDateItemList()
}
onMounted(() = > {
// Initialize the calendar to default the current month
changeMonth('today')})// Listen for the current selected date to update the view
watch(currentDate, () = > {
getDateItemList()
})
// Get the daily Settings style and action
let dateItemList: JSX.Element[] = []
const getDateItemList = () = > {
dateItemList = listOfDatesOfTheMonth.map(item= > {
Date can be a string or an array. See obj's definition
const isCurrentMonth = String(item.date).indexOf(currentMonth.value) === -1
// Calculate the bound class
const className = `dateItem ${isCurrentMonth ? ' ' : 'currentMonth'} ${currentDate.value === item.date ? 'currentDate' : ' '}`
return <div onClick={()= > { setCurrentDate(item.date + '') }} class={className}>{parseInt(item.day + '') }</div>})}// Last month, next month, current month
const changeMonth = (type: string) = > {
/ / today
if (type === 'setDate') {
currentMonth.value = moment(currentDate.value).format('YYYY-MM')}/ / today
if (type === 'today') {
currentMonth.value = moment().format('YYYY-MM')}/ / next month
if (type === 'nextMonth') {
currentMonth.value = moment(currentMonth.value).add(1.'month').format('YYYY-MM')}/ / last month
if (type === 'lastMonth') {
currentMonth.value = moment(currentMonth.value).subtract(1.'month').format('YYYY-MM')
}
currentDate.value = moment(currentMonth.value).format('YYYY-MM-DD')
generatedDate(currentMonth.value)
}
// Set the selected day for the current day
const setCurrentDate = (date:string) = > {
currentDate.value = date
// Regenerate the calendar with different months
if (date.indexOf(currentMonth.value) === -1) {
changeMonth('setDate')}}// Header week list
const weekItemList = weekList.map(item= > {
return <div class='dateItem'>{item}</div>
})
return () = > (
<div class='calendar-box'>
{currentDate.value}
<div class='header'>
<p>{currentMonth.value}</p>
<div class='operate'>
<p onClick={()= >{changeMonth('lastMonth')}}> lastMonth</p>
<p onClick={()= >{changeMonth('today')}}> Today</p>
<p onClick={()= >{changeMonth('nextMonth')}}> nextMonth</p>
</div>
</div>
<div class='weekBox'>{weekItemList}</div>
<div class='dateItemBox'>{dateItemList}</div>
</div>)}})Copy the code
// indenx.scss// Calendar component.calendar-box {
width: 430px;
border: 1px solid #ebeef5;
.header {
display: flex;
justify-content: space-between;
align-content: center;
padding: 5px;
border-bottom: 1px solid #ebeef5;
.operate {
display: flex;
justify-content: flex-end;
p {
padding: 5px 10px;
margin-left: 5px;
border-radius: 2px;
border: 1px solid #ebeef5;
cursor: pointer;
}
p:hover {
background: #f2f8fe; }}}.dateItemBox , .weekBox {
width: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.dateItem {
color: gray;
width: calc(100% / 7);
height: 40px;
border: 1px solid #ebeef5;
cursor: default;
}
.dateItem:nth-of-type(7n) {
margin-right: 0;
}
.dateItem:hover{
background: #f2f8fe;
}
.currentMonth{
color: # 303133;
}
.currentDate{
background: #f2f8fe; }}.weekBox{
.dateItem{
text-align: center;
line-height: 40px;
border: none; }}}Copy the code