业务开发场景中,经常遇到el-date-picker允许的最大跨度为一年的需求,但elm-ui的API中没有相关限制,所以封装一个最大跨度一年的组件是很有必要的。
1、v-model使用在自定义组件上
封装前先要了解,v-model其实也可以用在自定义组件上。
- 父组件内
<max-year-picker v-model="range"></max-year-picker>
- 子组件内
export default {
props: {
value: String
},
methods: {
handleInput(val) {
this.$emit('input', val)
}
}
}
v-model其实就是:value=“value”,然后加一个@input事件组合的语法糖,所以这里只需在子组件内emit一下input事件,就可以实现跨组件的v-model双向绑定。
2、组件实现
新建max-year-picker.vue
文件,主要通过pickerOptions
里的disabledDate来控制禁止选中的日期。实现思想就是,当选中第一个开始日期时,拿到该时间戳,然后控制接下来选中时间在一年以内。话不多说直接上代码
<template>
<el-date-picker
:value="value"
@input="handleInput"
:clearable="true"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions"
:editable="false"
:unlink-panels="true"
></el-date-picker>
</template>
<script>
export default {
props: {
value: {
type: Array,
default: () => []
}
},
data() {
return {
pickDate: {}, // 选中时间
pickerOptions: {
onPick: this.getPickDate,
disabledDate: this.disabledDate
}
}
},
methods: {
handleInput(val) {
this.$emit('input', val)
},
getPickDate(pick) {
this.pickDate = pick
},
disabledDate(date) {
const { minDate, maxDate } = this.pickDate
if (minDate && !maxDate) {
const diff = Math.abs(minDate.valueOf() - date.valueOf())
if (diff > 1000 * 3600 * 24 * 365) {
return true
}
}
}
}
}
</script>
父组件内调用也很简单,直接用v-model即可,无需额外绑定任何事件
<max-year-picker v-model="timeRange"></max-year-picker>
由于子组件内支持input事件,父组件也隐式包含input事件,所以子组件@input=“hanldeInput"完全可以用v-on=”$listeners"代替,优化后子组件如下
<template>
<el-date-picker
:value="value"
v-on="$listeners"
:clearable="true"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions"
:editable="false"
:unlink-panels="true"
></el-date-picker>
</template>
<script>
export default {
props: {
value: {
type: Array,
default: () => []
}
},
data() {
return {
pickDate: {}, // 选中时间
pickerOptions: {
onPick: this.getPickDate,
disabledDate: this.disabledDate
}
}
},
methods: {
getPickDate(pick) {
this.pickDate = pick
},
disabledDate(date) {
const { minDate, maxDate } = this.pickDate
if (minDate && !maxDate) {
const diff = Math.abs(minDate.valueOf() - date.valueOf())
if (diff > 1000 * 3600 * 24 * 365) {
return true
}
}
}
}
}
</script>
3、实现效果
总结:除了el-date-picker,element中其他组件,二次封装的时候都可以使用v-model + $listeners的方式,简单方便,有奇效。