写在前面
日期限制处理(禁用),下面我以我这边的需求为例,
选择的年份需等于或小于当前年份
选择的年份范围必须在三年之内
1.限制起始日期小于截止日期
1)根据用户选中的开始日期,置灰不可选的日期范围;
2)如果用户先选择截止日期,再选择的开始日期,且开始日期大于截止日期,清空截止日期;
<div class="min-wid data-flex-start" >
<span class="with-hide">年</span><span class="with-d with-s">年</span>
<div class="year-range-picker">
<el-date-picker
v-model="dateList[0]"
:picker-options="startDatePicker"
type="year"
placeholder="选择开始年"
size="mini"
class="year-picker"
format="yyyy"
value-format="yyyy"
@change="handleDateChange"
/>
<span class="range-word"> 至 </span>
<el-date-picker
:key="randomKey "
v-model="dateList[1]"
:picker-options="endDatePicker"
:default-value="dateDefaultShow"
type="year"
placeholder="选择结束年"
size="mini"
class="year-picker"
value-format="yyyy"
/>
</div>
</div>
data() {
return {
randomKey: 0,
startDatePicker: this.beginDate(),
endDatePicker: this.processDate(),
dateDefaultShow: '', // 日期选择器的日期默到选择的年份
datatimeStr: {
dateBegin: '',
endDataDate: ''
},
minNowDate: '',
maxNowDate: '',
dateList: ['', '']
}
}
methods: {
// 获取日期 disabledDate 函数用于定义哪些日期应该被禁用。禁止选择大于特定日期的日期。
// 选择年份范围选择时开始时间不能大于结束时间,结束时间不能小于开始时间
// 提出开始时间必须小于提出结束时间
beginDate() {
const self = this
return {
disabledDate(time) {
if (self.dateList[1] !== '') {
const fixedTime = new Date(time)
return fixedTime.getFullYear() > self.dateList[1]
}
}
}
},
// 提出结束时间必须大于提出开始时间
processDate() {
const self = this
return {
disabledDate(time) {
if (self.dateList[0] !== '') {
const fixedTime = new Date(time)
if ((Number(self.maxNowDate) - Number(self.dateList[0])) <= 2) {
return fixedTime.getFullYear() > self.maxNowDate || fixedTime.getFullYear() < self.dateList[0]
} else {
return fixedTime.getFullYear() > (self.maxNowDate - (Number(self.maxNowDate) - Number(self.dateList[0])) + 2) || fixedTime.getFullYear() < self.dateList[0]
}
}
}
}
},
// 获取最大日期
getMaxDate() {
getDataDate().then(res => {
// 默认结束年为有数据的最近年,默认开始年为默认结束年-2,即默认时间范围为3年
this.maxNowDate = res.slice(0, 4)
this.minNowDate = this.maxNowDate - 2
this.dateList[0] = this.minNowDate.toString()
this.dateList[1] = this.maxNowDate
// 强制刷新
this.$forceUpdate()
}).catch(err => {
console.log(err)
})
},
// 当开始日期改变时的处理函数
// 如果截止日期早于开始日期3年以上,将截止日期清空
handleDateChange() {
// 当选择的开始日期比结束日期早三年以上时,清空结束日期
if (this.dateList[1] - 2 > this.dateList[0]) {
this.dateList[1] = ''
// 改变数组内的值,强制刷新,清空结束日期的显示
this.randomKey = Math.random()
}
// 日期选择器定位到选择的开始年份
this.dateDefaultShow = this.dateList[0]
}
}
<style scoped>
/* 顶部样式 */
.card-head{
padding:12px 16px;
background-color: #fff;
position:relative;
}
/* 数据日期字体样式 */
.date-font{
color: var(---Gray-6, #78808F);
font-family: "PingFang SC";
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 166.667% */
}
/*弹性布局:两端对齐 */
.data-flex-sabw{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
/* 弹性布局:左对齐*/
.data-flex-start {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
/* 弹性布局:右对齐*/
.data-flex-end {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.tp-con{
width: 100%;
height: 56px;
box-sizing: border-box;
display: flex;
padding: 12px 0px;
align-items: flex-start;
gap: 20px;
}
/*隐藏显示,占位*/
.with-hide {
opacity: 0;
color: var(---Neutral-8, #292929);
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px; /* 157.143% */
}
.with-d {
width: 24px;
}
.with-t {
width: 80px;
}
.with-l {
width: 38px;
}
.with-s {
box-sizing: border-box;
padding-right: 8px;
color: var(---Neutral-8, #292929);
text-align: right;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px; /* 157.143% */
}
.st_line {
box-sizing: border-box;
margin: 0 2px;
width: 9px;
height: 22px;
color: var(---Gray-6, #78808F);
text-align: center;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px; /* 157.143% */
}
.min-wid{
min-width:160px;
}
.query-bt {
background-color: #00B0B0;
color: #FFF;
outline: none;
}
.center-deep{
hight: 100%;
width: 100%;
background-color: #fff;
margin-top: 16px;
}
/deep/ .treeselect-main {
width: 204px;
line-height: 28px;
}
/deep/ .vue-treeselect__placeholder {
line-height: 28px;
}
/deep/ .vue-treeselect__control {
height: 32px !important;
line-height: 32px;
border-radius: 4px;
}
/deep/.vue-treeselect__single-value {
font-size: 14px;
top: 0%;
color: #606266;
font-weight: 400;
}
/deep/.vue-treeselect__input {
height: 32px;
line-height: 32px;
}
/*顶部筛选器输入框宽度*/
/deep/.el-select el-select--small,el-input el-input--small el-input--suffix{
width: 100% !important;
flex: 1;
}
/*年范围选择器*/
.year-range-picker {
color: black;
text-align: center;
border: 1px solid #dcdfe6;
border-radius:4px;
line-height: 32px;
overflow: hidden;
display: flex;
margin: 4px 0;
}
/deep/.el-input--mini .el-input__inner {
height: 32px;
line-height: 32px;
border: none
}
.range-word {
box-sizing: border-box;
padding-top: 6px;
color: var(---Neutral-8, #292929);
text-align: right;
font-family: "PingFang SC";
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
}
.year-range-picker .year-picker {
max-width: 150px;
margin:0;
}
</style>
v-for里面数据层次太多,或者套的组件层级太多, 数据变了,页面没有重新渲染,需手动强制刷新。
解决方法:运用 this.$forceUpdate()强制刷新
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
知识点:vue $forceUpdate() 强制重新渲染及四种方案对比
Vue的双向绑定属于自动档;在特定的情况下,需要手动触发“刷新”操作,目前有四种方案可以选择:
刷新整个页面(最low的,可以借助route机制,不推荐)
使用v-if标记(比较low的,有时候不生效,不推荐)
使用内置的forceUpdate方法(较好的)
使用key-changing优化组件(最好的)
vue $forceUpdate() 强制重新渲染及四种方案对比
参考文章:
ElementUI 年份范围选择器 el-year-picker
点开是关联的组件-基于element-ui的年份范围选择器
vue中element-ui日期选择组件el-date-picker 清空所选时间,会将model绑定的值设置为null 问题 及 限制起止日期范围
vue elementui时间控件,(单框同时选)范围选择周,季,年。
element ui datepicker时间控件实现范围选择周,季,年。
ElementUI年份范围选择器功能实现
element ui的日期选择器动态设定年份,并默认显示在该年份范围的日期时间
vue2、vue3中使用$forceUpdate()
🚀写在最后
希望我的分享能够帮助到更多的人,如果觉得我的分享有帮助的话,请大家一键三连支持一下哦~
❤️原创不易,期待你的关注与支持~
点赞👍+收藏⭐️+评论✍️
😊之后我会继续更新前端学习小知识,关注我不迷路~