初衷:在工作的时候我们经常用到一些日期选择框,我发现尤其是用时间段选择的时候,elementui给我们的是一个数组,需要我们自己处理,把startDate和endDate提出来分开双向绑定的话可以减少很多操作,包括各种传值,封装后统一处理,后期维护起来就没有那么累。(ps:本文章只做了常用的date/daterange的处理)
- 首先看下封装后组件的用法
(1)这里是单个日期的时候,直接通过v-model绑定就可以了,跟elementui的原生组件没有任何区别
<date-picker
type="date"
v-model="value"
></date-picker>
(2)这是时间段的用法,vue2双向绑定多个值只能用这个写法,vue3就可以写多个v-model了
<date-picker
type="daterange"
:startDate.sync="params.startDate"
:endDate.sync="params.endDate"
></date-picker>
这样用起来是不是感觉好多了,就不需要再单独处理时间段格式了,并且组件内部可以统一风格,话不多说,让我们看看组件怎么实现的吧!
- 首先这是html代码,以及一些常用的自定义属性,这些属性如不能满足可以自行根据elemenui的文档扩展
<template>
<el-date-picker
v-model="date"
:type="type"
:format="format"
:value-format="valueFormat"
:range-separator="rangeSeparator"
:placeholder="placeholder"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
>
</el-date-picker>
</template>
}
export default {
data() {
return {
date: null
}
},
props: {
/**
* 显示类型 year/month/date/dates/months/years week/datetime/datetimerange/ daterange/monthrange
* 暂时只对 date/daterange(很常用) 做了处理,其他的建议用element原生的组件,自行处理数据
*/
type: {
type: String,
default: 'date'
},
value: {
type: String,
default: ''
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
// 文本格式
format: {
type: String,
default: 'yyyy-MM-dd'
},
// 绑定值格式(这里的日期格式化参照elementui的时间格式,并不是dayjs的)
valueFormat: {
type: String,
default: 'yyyy-MM-dd HH:mm:ss'
},
// 单个日期下的提示文案
placeholder: {
type: String,
default: '选择日期'
},
// daterange 模式下选框1的提示文案
startPlaceholder: {
type: String,
default: '开始日期'
},
// daterange 模式下选框2的提示文案
endPlaceholder: {
type: String,
default: '结束日期'
},
// 选择范围时的分隔符
rangeSeparator: {
type: String,
default: '至'
}
},
3.首先我们需要监听绑定的值:date,这里对null的情况单独做了处理,否则会报错,并且为null的时候,我没有区分type为date还是daterange的情况,单纯不想写太多if嵌套。这儿自定义了input事件是vue默认的model,有不清楚的小伙伴可以去了解一下vue2自定义v-model的相关知识。
methods: {
// 根据日期选框不同type进行处理
setDate(val) {
if (Array.isArray(val)) {
this.$emit('update:startDate', val[0])
this.$emit('update:endDate', val[1])
} else {
this.$emit('input', val)
}
}
},
watch: {
// 绑定值发生改变响应父组件
date: {
handler: function (newval, oldval) {
if (newval) {
this.setDate(newval)
} else {
this.$emit('input', '')
this.$emit('update:startDate', '')
this.$emit('update:endDate', '')
}
},
deep: true
}
}
4.接下来我们就要接收父组件传过来的默认值,对其处理,以便显示在选框上面
(1)这是type为daterange的情况
watch: {
// 默认开始时间和结束时间
startDate: {
handler: function (val) {
if (val) {
this.$set(this.date, 0, val)
}
},
immediate: true
},
endDate: {
handler: function (val) {
if (val) {
this.$set(this.date, 1, val)
}
},
immediate: true
},
}
(2)这是type为date的情况,这种情况我直接在监听type的时候处理了。监听type对date进行默认赋值,因为type为date和daterange时候空状态的值类型不同。
watch: {
type: {
handler: function (val) {
if (val == 'daterange') {
this.date = ['', '']
} else if (val == 'date') {
this.date = this.value
}
},
immediate: true
},
}
5.整个实现过程就是这样了,其实非常简单,主要是针对时间段的时候提取他的开始和结束时间,这样父组件就不需要再对数据进行处理,直接就可以拿到想要的值。并且后期需要统一换风格或者相关配置项的时候也更加方便。最后附上完整代码。
<template>
<el-date-picker
v-model="date"
:type="type"
:format="format"
:value-format="valueFormat"
:range-separator="rangeSeparator"
:placeholder="placeholder"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
>
</el-date-picker>
</template>
<script>
export default {
props: {
/**
* 显示类型 year/month/date/dates/months/years week/datetime/datetimerange/ daterange/monthrange
* 暂时只对 date/daterange(很常用) 做了处理,其他的建议用element原生的组件,自行处理数据
*/
type: {
type: String,
default: 'date'
},
value: {
type: String,
default: ''
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
// 文本格式
format: {
type: String,
default: 'yyyy-MM-dd'
},
// 绑定值格式(这里的日期格式化参照elementui的时间格式,并不是dayjs的)
valueFormat: {
type: String,
default: 'yyyy-MM-dd HH:mm:ss'
},
// 单个日期下的提示文案
placeholder: {
type: String,
default: '选择日期'
},
// daterange 模式下选框1的提示文案
startPlaceholder: {
type: String,
default: '开始日期'
},
// daterange 模式下选框2的提示文案
endPlaceholder: {
type: String,
default: '结束日期'
},
// 选择范围时的分隔符
rangeSeparator: {
type: String,
default: '至'
}
},
data() {
return {
date: null
}
},
methods: {
// 根据日期选框不同type进行处理
setDate(val) {
if (Array.isArray(val)) {
this.$emit('update:startDate', val[0])
this.$emit('update:endDate', val[1])
} else {
this.$emit('input', val)
}
}
},
watch: {
type: {
handler: function (val) {
if (val == 'daterange') {
this.date = ['', '']
} else if (val == 'date') {
this.date = this.value
}
},
immediate: true
},
// 默认开始时间和结束时间
startDate: {
handler: function (val) {
if (val) {
this.$set(this.date, 0, val)
}
},
immediate: true
},
endDate: {
handler: function (val) {
if (val) {
this.$set(this.date, 1, val)
}
},
immediate: true
},
// 绑定值发生改变响应父组件
date: {
handler: function (newval, oldval) {
if (newval) {
this.setDate(newval)
} else {
this.$emit('input', '')
this.$emit('update:startDate', '')
this.$emit('update:endDate', '')
}
},
deep: true
}
}
}
</script>
<style>
</style>
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END