问题描述
时间选择器选择日期、月份在项目中比较常见,比如查询历史记录,我们需要选择具体日期或者发请求,获取历史数据。所以我们需要对时间选择器做一些控制,比如历史记录查询的话,就不能选择当前日期和以后的日期了。所以就需要把当前日期和未来日期给禁用掉,本文记录一下相应的代码写法。
使用饿了么UI肯定是要用官方给到的api,这里我们使用的是picker-options和disabledDate去控制,附上官方文档地址链接: https://element.eleme.cn/#/zh-CN/component/date-picker
禁用日期案例
效果图
代码如下
<template>
<div id="app">
<el-date-picker
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
type="date"
placeholder="请选择日期"
v-model="dayDate"
:picker-options="setDisabled"
></el-date-picker>
</div>
</template>
<script>
export default {
data() {
return {
timer: null,
dayDate: "",
setDisabled: {
disabledDate(time) {
return time.getTime() > Date.now(); // 可选历史天、可选当前天、不可选未来天
// return time.getTime() > Date.now() - 8.64e7; // 可选历史天、不可选当前天、不可选未来天
// return time.getTime() < Date.now() - 8.64e7; // 不可选历史天、可选当前天、可选未来天
// return time.getTime() < Date.now(); // 不可选历史天、不可选当前天、可选未来天
},
},
};
},
/*
8.64e7 是科学计数法 8.64乘以10的7次方,即为86400000也就是 1000*60*60*24 也就是一天的毫秒数。因为Date.now()
方法能够返回得到自1970年1月1日00:00:00(UTC)到当前时间的毫秒数。咱们是北京时间的时区,也就是为东8区,
起点时间对应就是:"1970/01/01 08:00:00"
picker-options需要一个最终的布尔值,所以是否减去8.64e7也就是是否往前推移一天,也就是是否包含当前的天数
*/
};
</script>
<style lang="less" scoped>
#app {
width: 950px;
height: 600px;
box-sizing: border-box;
margin: 50px;
}
</style>
禁用日期简单,下面我们说一下禁用月份,禁用月份需要对日期格式做一个转换并判断即可
禁用月份案例
效果图
代码如下
<template>
<div id="app">
<el-date-picker
v-model="value"
format="yyyy-MM"
value-format="yyyy-MM"
type="month"
placeholder="请选择月份"
:picker-options="setMonthDisabled"
>
</el-date-picker>
</div>
</template>
<script>
export default {
data() {
return {
value: "",
setMonthDisabled: {
disabledDate(time) {
// 获取当前的月份信息
const date = new Date(); // 获取当前的时间基本信息,值是这样的: Tue Jul 20 2021 14:59:43 GMT+0800 (中国标准时间)
const year = date.getFullYear(); // 获取当前年份,值是这样的: 2021
let month = date.getMonth() + 1; // 获取当前月份,值是这样的: 6 getMonth()方法返回值是0-11,也就是1月份到12月份,所以要加上1,才是当前月份
if (month >= 1 && month <= 9) {
// 如果是1月到9月就要在前面补上一个0 比如:02、07 月份这样表示
month = "0" + month;
}
const nowDate = year.toString() + month.toString(); // 转换成字符串拼接,最终得到年和月,比如此时的时间是2021年7月20号,所以nowDate的值是:202107
// 获取时间选择器的月份信息
const timeyear = time.getFullYear(); // 获取时间选择器的年份(有很多)
let timemonth = time.getMonth() + 1; // 与上面同理
if (timemonth >= 1 && timemonth <= 9) {
timemonth = "0" + timemonth;
}
const elTimeData = timeyear.toString() + timemonth.toString();
// 返回,时间选择器的日期月份大于当前日期的月份,又因为disabledDate函数是控制月份禁用不可选
// 所以,最终就是:时间选择器的月份大于当前的月份,就都禁用掉,所以就实现了最终效果:
// 大于等于当前月份都不可选
return elTimeData <= nowDate; // 这里虽然是字符串,但是弱类型语言js会做一个转换,是可以比较大小的如: '202107' > '202008'
},
},
};
},
methods: {},
};
</script>
<style lang="less" scoped>
#app {
width: 950px;
height: 600px;
box-sizing: border-box;
margin: 50px;
}
</style>
前后各一年
<template>
<div id="box">
<el-date-picker
format="yyyy-MM"
value-format="yyyy-MM"
v-model="value"
type="month"
placeholder="选择月"
:picker-options="setMonthDisabled"
>
</el-date-picker>
</div>
</template>
<script>
export default {
data() {
return {
value: "",
setMonthDisabled: {
disabledDate(time) {
// 获取当前的月份信息
const date = new Date();
const year = date.getFullYear();
let month = date.getMonth() + 1;
if (month >= 1 && month <= 9) {
month = "0" + month;
}
const minNowDate = (year-1).toString() + month.toString(); // 获取当前时间往前推算一年的月份
const maxNowDate = (year+1).toString() + month.toString(); // 获取当前时间往后推算一年的月份
// 获取时间选择器的月份信息
const timeyear = time.getFullYear();
let timemonth = time.getMonth() + 1;
if (timemonth >= 1 && timemonth <= 9) {
timemonth = "0" + timemonth;
}
const elTimeData = timeyear.toString() + timemonth.toString();
// 把时间选择器小于最小的禁掉,大于最大的也禁用掉,这样的话就只能选择以当前时间点为原点,前后各一年的范围啦
return elTimeData < minNowDate | elTimeData > maxNowDate
},
},
};
},
};
</script>
<style lang="less" scoped>
#box {
width: 100%;
height: 600px;
box-sizing: border-box;
padding: 50px;
}
</style>
其实写法也是多样的,欢迎大家共同交流学习,共同进步
补充~月份面板里的中文月份替换成数字月份
道友说,把月份面板中的中文月份替换成数字月份,解法有两种:
- 修改源码
- 障眼法替换dom的innerHtml
笔者的解法是第二种,毕竟方便一些,如下:
效果图
代码
请看代码和注释
<template>
<div class="wrap">
<el-date-picker
@focus="focusFn"
v-model="value"
type="month"
placeholder="选择月"
>
</el-date-picker>
</div>
</template>
<script>
// 6. 对象字典匹配形式,或者使用switch case也行
function chineseToNum(month) {
let monthObj = {
一月: "1月",
二月: "2月",
三月: "3月",
四月: "4月",
五月: "5月",
六月: "6月",
七月: "7月",
八月: "8月",
九月: "9月",
十月: "10月",
十一月: "11月",
十二月: "12月",
};
// 7. 将中文月份更改为数字月份
return monthObj[month];
}
let numMonthArr = [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月",
];
export default {
data() {
return {
value: "",
};
},
methods: {
// 1. 当月份时间选择器获取焦点的时候会弹出月份面板
focusFn() {
// 2. 要等到dom渲染完毕后,才能做dom内容替换,故使用$nextTick
this.$nextTick(() => {
// 3. 获取月份面板内的承载月份文字的a标签,建议大家审查dom看一下
let monthArr = document.querySelectorAll(
".el-month-table tbody tr td a"
);
// 8. 后续再获取焦点摊开月份面板的时候,需要看看是否已经做了中文转数字替换
if (numMonthArr.includes(monthArr[0].innerHTML)) {
// 9. 要是替换过了就不操作了即可
return;
}
// 4. 然后循环这个dom数组
for (let i = 0; i < monthArr.length; i++) {
let aDom = monthArr[i];
// 5. 然后把a标签的中文内容更改为数字内容
aDom.innerHTML = chineseToNum(aDom.innerHTML);
}
});
},
},
};
</script>