-
效果
image_0.9073671515884494.gif
- 今日学习简单的日历列表
- 首先创建项目,应该都会
- 简单的时间的api说下
new Date getFullYear() getMonth()
new Date('2023,'1',0) 这是获取1月的最后一天,月份是+1的,此时的月是2月,获取1月的最后一天
- 首先简单的布局及标题年月的展示
const date = ref(new Date())
const month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const week = ["日", "一", "二", "三", "四", "五", "六"]
<ul class="flexr flex-s-a">
<li @click="pre"><</li>
<li>{{ date.getFullYear() }}年{{ month[date.getMonth()] }}月</li>
<li @click="next">></li>
</ul>
<ul class="flexr f-w m-t-20">
<li class="day" v-for="(item, index) in week" :key="index">
{{ item }}
</li>
</ul>
- 实现切换月的功能(上个月,下个月)
const pre = () => {
// 返回上一个月的第一天起
date.value = new Date(
date.value.getFullYear(),
date.value.getMonth() - 1,
1
)
}
const next = () => {
date.value = new Date(
date.value.getFullYear(),
date.value.getMonth() + 1,
1
)
}
- 接下来实现天数的渲染
// 获取天数
const getday = computed({
get() {
{
const days = [] //{ day:'',text: "" ,botttmInfo:''}
// 获取当前月份的第一天的周几,通过周几添加前面有几个空数据的
const firstd =
new Date(
date.value.getFullYear(),
date.value.getMonth(),
1
).getDay() + ""
// 获取当前月份的最后一天
const lastd =
new Date(
date.value.getFullYear(),
date.value.getMonth() + 1,
0
).getDate() + ""
// 添加当前前面展示的空
for (let index = 0; index < firstd; index++) {
days.push({ day: "", text: "", bottomInfo: "", date: "" })
}
// 添加天数
for (let index = 1; index <= lastd; index++) {
days.push({
day: index,
text: index,
bottomInfo: "",
date: new Date(
date.value.getFullYear(),
date.value.getMonth(),
index
),
})
}
return days
}
},
})
<ul class="flexr f-w m-t-20">
<li class="day" v-for="(item, index) in week" :key="index">
{{ item }}
</li>
<template v-for="(item, i) in getday" :key="'i' + i">
<li
:class="[
'day',
active === item.day
? 'ac'
: '',
]"
@click="db(item.day)"
>
<p :style="{ lineHeight: item.bottomInfo ? '' : '40px' }">
{{ item.text ? item.text : item.day }}
</p>
<p
v-if="item.bottomInfo && (item.text || item.day)"
>
{{ item.bottomInfo }}
</p>
</li>
</template>
</ul>
- 此时简单的功能就实现啦,切换月份下面的数据也会进行渲染
-
可以加点其他功能(默认赋值,回调当前点击的月份,当前月份当前的天数之前默认置灰等)
image.png
- 当前月份的当前天数之前的置灰,点击事件的回调
用一个变量进行存储当前的天数和月份(初始化,点击之后进行更新)
const active = ref({
m: date.value.getMonth() + 1,
m1: date.value.getMonth() + 1,
d: date.value.getDate(), //样式的切换
s: date.value.getDate(), //当前的天数进行保存,对比
})
const db = (i) => {
if (i < active.value.s && active.value.m >= date.value.getMonth() + 1)
return
active.value.d = i
active.value.m1 = date.value.getMonth() + 1
emit("change", {
date:
date.value.getFullYear() +
"/" +
(date.value.getMonth() + 1) +
"/" +
i,
})
}
核心代码
<li
:class="[
'day',
active.d == item.day && active.m1 == date.getMonth() + 1
? 'ac'
: '',
(active.m == date.getMonth() + 1 &&
item.day < new Date().getDate()) ||
active.m > date.getMonth() + 1
? 'ag'
: '',
]"
@click="db(item.day)"
>
-
默认值的替换
image.png
-
整体的代码
<script>
import { computed, ref, watch } from "vue"
export default {
name: "",
components: {},
props: {
value: {
typeof: Date,
default: () => new Date(),
},
f: {
typeof: Array,
default: [],
},
fontSize: {
typeof: String,
default: "10px",
},
},
emits: ["change", "formatter"],
setup(props, { emit }) {
const month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const week = ["日", "一", "二", "三", "四", "五", "六"]
const date = ref(props.value)
const pre = () => {
// 返回上一个月的第一天起
date.value = new Date(
date.value.getFullYear(),
date.value.getMonth() - 1,
1
)
}
const next = () => {
date.value = new Date(
date.value.getFullYear(),
date.value.getMonth() + 1,
1
)
}
// 获取天数
const getday = computed({
get() {
{
const days = [] //{ day:'',text: "" ,botttmInfo:''}
// 获取当前月份的第一天的周几,通过周几添加前面有几个空数据的
const firstd =
new Date(
date.value.getFullYear(),
date.value.getMonth(),
1
).getDay() + ""
// 获取当前月份的最后一天
const lastd =
new Date(
date.value.getFullYear(),
date.value.getMonth() + 1,
0
).getDate() + ""
// 添加当前前面展示的空
for (let index = 0; index < firstd; index++) {
days.push({ day: "", text: "", bottomInfo: "", date: "" })
}
// 添加天数
for (let index = 1; index <= lastd; index++) {
days.push({
day: index,
text: index,
bottomInfo: "",
date: new Date(
date.value.getFullYear(),
date.value.getMonth(),
index
),
})
}
//直接在emit传递days就不用watch监听,但是用户可以修改day,导致页面问题
// const d = days.map((item) => {
// return {
// text: item.text,
// bottomInfo: item.bottomInfo,
// date: item.text
// ? new Date(
// date.value.getFullYear(),
// date.value.getMonth(),
// item.text
// )
// : "",
// }
// })
emit("formatter", days)
return days
}
},
})
// watch(
// () => props.f,
// (newV) => {
// console.log("newV", newV)
// newV.forEach((item) => {
// getday.value.forEach((val) => {
// val.text = item.text
// val.bottomInfo = item.bottomInfo
// })
// })
// }
// )
const active = ref({
m: date.value.getMonth() + 1,
m1: date.value.getMonth() + 1,
d: date.value.getDate(), //样式的切换
s: date.value.getDate(), //当前的天数进行保存,对比
})
const db = (i) => {
if (i < active.value.s && active.value.m >= date.value.getMonth() + 1)
return
active.value.d = i
active.value.m1 = date.value.getMonth() + 1
emit("change", {
date:
date.value.getFullYear() +
"/" +
(date.value.getMonth() + 1) +
"/" +
i,
})
}
return { week, date, month, pre, next, getday, active, db }
},
}
</script>
<template>
<div class="calendar">
<h4>日历模板</h4>
<div class="wrap">
<ul class="flexr flex-s-a">
<li @click="pre"><</li>
<li>{{ date.getFullYear() }}年{{ month[date.getMonth()] }}月</li>
<li @click="next">></li>
</ul>
<ul class="flexr f-w m-t-20">
<li class="day" v-for="(item, index) in week" :key="index">
{{ item }}
</li>
<template v-for="(item, i) in getday" :key="'i' + i">
<li
:class="[
'day',
active.d == item.day && active.m1 == date.getMonth() + 1
? 'ac'
: '',
(active.m == date.getMonth() + 1 &&
item.day < new Date().getDate()) ||
active.m > date.getMonth() + 1
? 'ag'
: '',
]"
@click="db(item.day)"
>
<p :style="{ lineHeight: item.bottomInfo ? '' : '40px' }">
{{ item.text ? item.text : item.day }}
</p>
<p
v-if="item.bottomInfo && (item.text || item.day)"
:style="{ fontSize }"
>
{{ item.bottomInfo }}
</p>
</li>
</template>
</ul>
</div>
</div>
</template>
<style lang="scss">
.calendar {
width: 100%;
height: 100%;
text-align: center;
.wrap {
width: 600px;
border: 1px solid #ccc;
margin: 20px auto;
box-sizing: border-box;
padding: 20px 40px;
}
.flexr {
display: flex;
align-items: center;
}
.flex-s-a {
justify-content: space-around;
}
.m-t-20 {
margin-top: 20px;
}
.f-w {
flex-wrap: wrap;
}
.day {
width: calc(100% / 7);
height: 60px;
box-sizing: border-box;
padding: 10px 0;
}
.ac {
background: #f00;
color: #000;
}
.ag {
color: #ccc;
}
}
</style>
- 当然上面控制选中的还有更好的方法,可以在评论区讨论一下!如果你有疑问,可以留言!
网友评论