使用了 Element UI 中的 el-date-picker 组件,并对其进行了进一步封装和定制
创建组件index.vue (src/common-ui/datePicker/index.vue)
vue
<template>
<el-date-picker
v-model="hValue"
ref="datePicker"
:align="align"
:key="poperKeyValue"
:clear-icon="clearIcon"
:clearable="clearable"
:default-value="defaultValue"
:default-time="defaultTime"
:disabled="disabled"
:editable="editable"
:end-placeholder="endPlaceholder"
:format="format"
:name="name"
:picker-options="pickerOptions"
:placeholder="placeholder"
:popper-class="poperClass"
:prefix-icon="prefixIcon"
:range-separator="rangeSeparator"
:readonly="readonly"
:size="size"
:start-placeholder="startPlaceholder"
:type="type"
:unlink-panels="unlinkPanels"
:validate-event="validateEvent"
:value-format="valueFormat"
@blur="handleBlur"
@change="handleChange"
@focus="handleFocus"
:class="[
clearable ? '' : 'no-close'
]"
>
<slot name="range-separator" slot="range-separator"></slot>
</el-date-picker>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'HDatePicker',
props: {
keyValue: {
type: String,
default: 'datePick'
},
align: {
type: String,
validator (value) {
return ['left', 'center', 'right'].indexOf(value) !== -1
}
},
clearIcon: {
type: String,
default: 'el-icon-circle-close'
},
clearable: {
type: Boolean,
default: false
},
defaultValue: Date,
defaultTime: {
type: [String, Array],
validator (value) {
if (typeof value === 'string') {
return true
} else if (value instanceof Array) {
if (value.length !== 2) {
return false
}
for (let i = 0; i < value.length; i++) {
if (typeof value[i] !== 'string') {
return false
}
}
return true
}
return false
}
},
disabled: {
type: Boolean,
default: false
},
editable: {
type: Boolean,
default: false
},
endPlaceholder: String,
format: String,
name: String,
pickerOptions: {
type: Object,
validator ({ disabledDate, firstDayOfWeek, onPick, shortcuts }) {
if (disabledDate !== undefined && typeof disabledDate !== 'function') {
return false
}
if (
firstDayOfWeek !== undefined &&
[1, 2, 3, 4, 5, 6, 7].indexOf(firstDayOfWeek) === -1
) {
return false
}
if (onPick !== undefined && typeof onPick !== 'function') {
return false
}
if (shortcuts !== undefined) {
if (!(shortcuts instanceof Array)) {
return false
}
for (let i = 0; i < shortcuts.length; i++) {
let { text, onClick } = shortcuts[i]
if (
!text ||
typeof text !== 'string' ||
!onClick ||
typeof onClick !== 'function'
) {
return false
}
}
}
return true
}
},
placeholder: String,
popperClass: {
type: String,
default: 'date-picker-default'
},
prefixIcon: String,
rangeSeparator: {
type: String,
default: () => {
return '至'
}
},
readonly: {
type: Boolean,
default: false
},
shortcuts: {
type: Array,
default () {
return []
},
validator (value) {
let options = [
'today',
'yesterday',
'weekAgo',
'monthAgo',
'yearAgo',
'lastDay',
'lastWeek',
'lastMonth',
'lastYear'
]
for (let i = 0; i < value.length; i++) {
if (options.indexOf(value[i]) === -1) {
return false
}
}
return true
}
},
size: {
type: String,
validator (value) {
return ['medium', 'small', 'mini'].indexOf(value) !== -1
}
},
startPlaceholder: String,
type: {
type: String,
validator (value) {
return (
[
'date',
'daterange',
'datetime',
'datetimerange',
'dates',
'week',
'month',
'year',
'monthrange'
].indexOf(value) !== -1
)
}
},
unlinkPanels: {
type: Boolean,
default: false
},
validateEvent: {
type: Boolean,
default: true
},
value: {
type: [Date, String, Array],
required: true
},
valueFormat: String
},
data () {
return {
hValue: '',
clickOutsideFlag: false,
childHandleClose: null,
poperClass: '',
poperKeyValue: ''
}
},
created () {
this.shortcuts.forEach(type => {
let text
let onClick
if (this.type === 'date' || this.type === 'dateTime') {
switch (type) {
case 'today':
text = '今天'
onClick = function (picker) {
picker.$emit('pick', new Date())
}
break
case 'yesterday':
text = '昨天'
onClick = function (picker) {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24)
picker.$emit('pick', date)
}
break
case 'weekAgo':
text = '一周前'
onClick = function (picker) {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', date)
}
break
case 'monthAgo':
text = '一个月前'
onClick = function (picker) {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', date)
}
break
case 'yearAgo':
text = '一年前'
onClick = function (picker) {
const date = new Date()
date.setTime(date.getTime() - 3600 * 1000 * 24 * 365)
picker.$emit('pick', date)
}
break
}
} else if (this.type === 'daterange' || this.type === 'datetimerange') {
switch (type) {
case 'lastDay':
text = '最近一天'
onClick = function (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
picker.$emit('pick', [start, end])
}
break
case 'lastWeek':
text = '最近一周'
onClick = function (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
break
case 'lastMonth':
text = '最近一月'
onClick = function (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
break
case 'lastYear':
text = '最近一年'
onClick = function (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 365)
picker.$emit('pick', [start, end])
}
break
}
}
if (text) {
this.pickerOptions.shortcuts.push({
text,
onClick
})
}
})
this.$nextTick(() => {
if(this.$refs.datePicker) {
this.childHandleClose = this.$refs.datePicker.handleClose
this.$refs.datePicker.handleClose = this.handleClose
}
})
this.hValue = this.value
},
computed: {
...mapGetters(['defaultTheme', 'windowWidth'])
},
watch: {
value (val) {
this.hValue = val
this.updateInput()
},
hValue (val) {
if (val === null) {
this.hValue = ''
}
this.updateInput()
},
keyValue (val) {
this.poperKeyValue = val
},
windowWidth: {
handler (val) {
if (this.defaultTheme == 'dark') {
if (this.windowWidth <= 1024) {
this.poperClass = 'date-picker-dark date-picker-dark-width'
} else {
this.poperClass = 'date-picker-dark'
}
} else {
if (this.windowWidth <= 1024) {
this.poperClass = 'date-picker-default date-picker-default-width'
} else {
this.poperClass = 'date-picker-default'
}
}
},
immediate: true,
deep: true
},
poperClass: {
handler (val) {
this.poperKeyValue = this.keyValue + val
},
immediate: true
},
defaultTheme: {
handler (val) {
if (val == 'dark') {
if (this.windowWidth <= 1024) {
this.poperClass = 'date-picker-dark date-picker-dark-width'
} else {
this.poperClass = 'date-picker-dark'
}
} else {
if (this.windowWidth <= 1024) {
this.poperClass = 'date-picker-default date-picker-default-width'
} else {
this.poperClass = 'date-picker-default'
}
}
},
immediate: true
}
},
methods: {
handleBlur (event) {
this.$emit('blur', event)
},
handleChange () {
if (!this.clickOutsideFlag) {
this.updateInput()
let value = this.hValue || ''
this.$emit('input', value)
this.$emit('change', value)
} else {
this.clickOutsideFlag = false
this.hValue = this.value
}
},
handleFocus (event) {
this.$emit('focus', event)
},
focus () {
this.$refs.datePicker.focus()
},
handleClose () {
if (this.$refs.datePicker.pickerVisible) {
this.clickOutsideFlag = true
this.childHandleClose()
}
},
updateInput () {
this.$nextTick(() => {
if (this.$refs.datePicker.$refs.reference.$refs) {
this.$refs.datePicker.$refs.reference.$refs.input.value = this.value
}
})
}
}
}
</script>
<style lang="scss" scoped></style>
页面引入
- 在需要使用HDatePicker组件的地方,通过import语句引入组件注册并使用
vue
<template>
<div>
<h-date-picker
v-model="selectedValue"
:clearable="info.clearable"
:start-placeholder="
info.startPlaceholder ? info.startPlaceholder : ''
"
:end-placeholder="info.endPlaceholder ? info.endPlaceholder : ''"
:placeholder="info.placeholder || ''"
:type="info.dateType"
:value-format="info.valueFormat"
:prefix-icon="'el-icon-caret-bottom'"
:disabled="info.disabled"
:picker-options="info.pickerOptions"
></h-date-picker>
</div>
</template>
<script>
import HDatePicker from '@/common-ui/datePicker/index'
export default {
components: {
HDatePicker
},
data() {
return {
info:{
clearable: true,
dateType:'date',
valueFormat:'yyyy-MM-dd',
disabled: false,
pickerOptions:{}
},
dataSource: [],
selectedValue: ''
}
},
methods: {
}
// ...
}
</script>
确保你已经安装了Vue.js和Element UI,并在项目中引入它们。