Vue 日期选择器组件 - 简洁易用, 可自定义样式
<p>"<template>\n <div class="datetime-picker" :style="{ width: width }">\n <input type="text" :style="styleObj" :readonly="readonly" v-model="showValue" @click="show = !show">\n <div class="picker-wrap" v-show="show">\n <table class="date-picker">\n <thead>\n <tr class="date-head">\n <th colspan="4">\n <span class="btn-prev" @click="yearClick(-1)"><</span>\n <span class="show-year">{{ now.getFullYear() }}</span>\n <span class="btn-next" @click="yearClick(1)">></span>\n </th>\n <th colspan="3">\n <span class="btn-prev" @click="monthClick(-1)"><</span>\n <span class="show-month">{{ months[now.getMonth()] }}</span>\n <span class="btn-next" @click="monthClick(1)">></span>\n </th>\n </tr>\n <tr class="date-days">\n <th v-for="day in days" :key="day">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for="i in 6" :key="i">\n <td v-for="j in 7" :key="j" :class="date[i * 7 + j] && date[i * 7 + j].status"\n :date="date[i * 7 + j] && date[i * 7 + j].date" @click="pickDate(i * 7 + j)">{{ date[i * 7 + j] && date[i *\n 7\n + j].text }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n</template>\n\n<script>\n export default {\n props: {\n width: { type: String, default: '238px' },\n readonly: { type: Boolean, default: false },\n value: { type: String, default: '' },\n format: { type: String, default: 'YYYY-MM-DD' },\n styleObj: { type: Object, default: null }\n },\n data() {\n return {\n show: false,\n showValue: '',\n days: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],\n months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\n date: [],\n now: new Date()\n }\n },\n watch: {\n now() {\n this.update()\n },\n show() {\n this.update()\n }\n },\n methods: {\n close() {\n this.show = false\n },\n update() {\n var arr = []\n var time = new Date(this.now)\n time.setMonth(time.getMonth(), 1) // the first day\n var curFirstDay = time.getDay()\n curFirstDay === 0 && (curFirstDay = 7)\n time.setDate(0) // the last day\n var lastDayCount = time.getDate()\n for (let i = curFirstDay; i > 0; i--) {\n arr.push({\n text: lastDayCount - i + 1,\n time: new Date(time.getFullYear(), time.getMonth(), lastDayCount - i + 1),\n status: 'date-pass'\n })\n }\n\n time.setMonth(time.getMonth() + 2, 0) // the last day of this month\n var curDayCount = time.getDate()\n time.setDate(1) // fix bug when month change\n var value = this.value || this.stringify(new Date())\n for (let i = 0; i < curDayCount; i++) {\n let tmpTime = new Date(time.getFullYear(), time.getMonth(), i + 1)\n let status = ''\n this.stringify(tmpTime) === value && (status = 'date-active')\n arr.push({\n text: i + 1,\n time: tmpTime,\n status: status\n })\n }\n\n var j = 1\n while (arr.length < 42) {\n arr.push({\n text: j,\n time: new Date(time.getFullYear(), time.getMonth() + 1, j),\n status: 'date-future'\n })\n j++\n }\n this.date = arr\n },\n yearClick(flag) {\n this.now.setFullYear(this.now.getFullYear() + flag)\n this.now = new Date(this.now)\n },\n monthClick(flag) {\n this.now.setMonth(this.now.getMonth() + flag)\n this.now = new Date(this.now)\n },\n pickDate(index) {\n this.show = false\n this.now = new Date(this.date[index].time)\n this.showValue = this.stringify()\n this.$emit('on-change', this.showValue)\n },\n parse(str) {\n var time = new Date(str)\n return isNaN(time.getTime()) ? null : time\n },\n stringify(time = this.now, format = this.format) {\n var year = time.getFullYear()\n var month = time.getMonth() + 1\n var date = time.getDate()\n var monthName = this.months[time.getMonth()]\n\n var map = {\n YYYY: year,\n MMM: monthName,\n MM: ('0' + month).slice(-2),\n M: month,\n DD: ('0' + date).slice(-2),\n D: date\n }\n return format.replace(/Y+|M+|D+/g, function (str) {\n return map[str]\n })\n },\n leave(e) {\n if (!this.$el.contains(e.target)) {\n this.close()\n }\n }\n },\n mounted() {\n this.now = this.parse(this.value) || new Date()\n document.addEventListener('click', this.leave, false)\n },\n beforeDestroy() {\n document.removeEventListener('click', this.leave, false)\n }\n}\n</script>\n\n<style scoped>\n.datetime-picker {\n position: relative;\n display: inline-block;\n font-family: "Segoe UI", "Lucida Grande", Helvetica, Arial, "Microsoft YaHei";\n -webkit-font-smoothing: antialiased;\n color: #333;\n}\n\n.datetime-picker * {\n box-sizing: border-box;\n}\n\n.datetime-picker input {\n width: 100%;\n padding: 5px 10px;\n height: 30px;\n outline: 0 none;\n border: 1px solid #ccc;\n font-size: 13px;\n}\n\n.datetime-picker .picker-wrap {\n position: absolute;\n z-index: 1000;\n width: 238px;\n height: 280px;\n margin-top: 2px;\n background-color: #fff;\n box-shadow: 0 0 6px #ccc;\n}\n\n.datetime-picker table {\n width: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n text-align: center;\n font-size: 13px;\n}\n\n.datetime-picker tr {\n height: 34px;\n border: 0 none;\n}\n\n.datetime-picker th, \n.datetime-picker td {\n user-select: none;\n width: 34px;\n height: 34px;\n padding: 0;\n border: 0 none;\n line-height: 34px;\n text-align: center;\n}\n\n.datetime-picker td {\n cursor: pointer;\n}\n\n.datetime-picker td:hover {\n background-color: #f0f0f0;\n}\n\n.datetime-picker td.date-pass, \n.datetime-picker td.date-future {\n color: #aaa;\n}\n\n.datetime-picker td.date-active {\n background-color: #ececec;\n color: #3bb4f2;\n}\n\n.datetime-picker .date-head {\n background-color: #3bb4f2;\n text-align: center;\n color: #fff;\n font-size: 14px;\n}\n\n.datetime-picker .date-days {\n color: #3bb4f2;\n font-size: 14px;\n}\n\n.datetime-picker .show-year {\n display: inline-block;\n min-width: 62px;\n vertical-align: middle;\n}\n\n.datetime-picker .show-month {\n display: inline-block;\n min-width: 28px;\n vertical-align: middle;\n}\n\n.datetime-picker .btn-prev, \n.datetime-picker .btn-next {\n cursor: pointer;\n display: inline-block;\n padding: 0 10px;\n vertical-align: middle;\n}\n\n.datetime-picker .btn-prev:hover, \n.datetime-picker .btn-next:hover {\n background: rgba(16, 160, 234, 0.5);\n}\n</style>\n</p>
原文地址: https://www.cveoy.top/t/topic/pyYj 著作权归作者所有。请勿转载和采集!