这篇文章用来分享自己项目中做el-calendar日历组件封装时的一些实用功能和踩的一些坑吧,毕竟ElementUI官方文档上对这个组件的描述实在太少了。
1、给每一天增加可输入的input框
其实这个功能在官方文档上基本已经实现了(在“自定义内容”那一块),直接在slot插槽里再加个input即可。
<el-calendar v-model="calendarDate">
<template slot="dateCell" slot-scope="{ date, data }">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split("-").slice(1).join("-") }}
{{ data.isSelected ? "✔️" : "" }}
</p>
<el-input
v-if="data.type == 'current-month'"
:disabled="timeOptions(date)"
v-model="calendarData[date.getDate() - 1]"
step="0.01"
type="number"
size="mini"
:min="0"
>
</el-input>
</template>
</el-calendar>
input框双向绑定的是一个calendarData数组里对应下标的对应值,数组长度为当月天数-1,比如当月有30天,则每天绑定的值为calendarData[0]~calendarData[29],故为calendarData[date.getDate() - 1]。
这里我还根据项目需求加了一个禁用规则:超过当前日期的时间和跨上上月的时间,数据不允许修改,input框为禁用状态::disabled="timeOptions(date)"
methods:
// 验证可输入有效日期
timeOptions(date) {
return (
date > moment().endOf("day").toDate() ||
date < moment().startOf("month").subtract(1, "months").toDate()
);
},
效果:
2、el-input框的type=number时,去掉上下箭头按钮
想让input输入框只能输入数字,又嫌麻烦懒得写rules,就会直接用type=number。但这样一来就会有个在标签属性上去除不掉的上下箭头按钮,如图中的红框:
本来输入框是保留两位小数的,有了这个按钮后直接把小数第二位挡住了。
直接从css入手来隐藏掉它:
<style scoped>
::v-deep input::-webkit-outer-spin-button,
::v-deep input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
}
::v-deep input[type="'number'"] {
-moz-appearance: textfield !important;
}
</style>
这样一来就ok了
3、设置一个月计划输入框,输入后的值平均填入每日的数据中
这个是项目上的需求,可能适用场景也不广,也放出来仅供参考吧。(因为我们是粗略计算每个月的碳排放量,所以数值不需要特别精确,就只保留到小数点后两位了)
若选择的日期是当月,例如今天是4月22日,则只平均填入到当日为止,当日后的输入框不能填入数据:
代码:
<el-input
v-model="setSum"
type="Number"
size="mini"
:min="0"
:disabled="judgeDate(calendarDate)"
>
</el-input>
<el-calendar v-model="calendarDate">
<template slot="dateCell" slot-scope="{ date, data }">
<p :class="data.isSelected ? 'is-selected' : ''">
{{ data.day.split("-").slice(1).join("-") }}
{{ data.isSelected ? "✔️" : "" }}
</p>
<el-input
v-if="data.type == 'current-month'"
:disabled="timeOptions(date)"
v-model="calendarData[date.getDate() - 1]"
step="0.01"
type="number"
size="mini"
:min="0"
>
</el-input>
</template>
</el-calendar>
data() {
return {
setSum: 0,
calendarData: [0],
};
},
computed: {
// 先判断是否为当月,若是,则天数返回本月到今日为止的总天数,反之则返回当月的总天数。
days() {
if (
moment(this.calendarDate).format("YYYY-MM") !=
moment().format("YYYY-MM")
) {
return moment(this.calendarDate).endOf("month").date();
} else {
return moment().date();
}
},
},
watch: {
setSum(val) {
// 平分到每天
// let dayValue = Math.round(val/this.days);
let dayValue = (val / this.days).toFixed(2);
this.calendarData = new Array(this.days).fill(dayValue);
},
},
4、设置一个月计划输入框,输入后的值平均填入每日的数据中
和上条搭配使用的一个需求,求出该月每日数据的总和作为月合计量。
业务逻辑是先填写月计划量,平均到每日的数据,再单独修改特殊日期内的碳排放量,总和得到月合计量,而该月合计量才是真正要通过接口传入数据库的实际碳排放月总值
代码:
<el-form-item :label="$t('lang.MonthlyEmissionTotal')">
<el-input v-model="calendarDataSum" size="mini" :min="0" disabled>
</el-input>
</el-form-item>
computed: {
calendarDataSum() {
return this.calendarData
.map((item) => Number(item))
.reduce((total, value) => total + value)
.toFixed(2);
},
},
完整代码等整个组件优化完后再一起发出来~