<p>&quot;<template>\n  <div class="datetime-picker" :style="{ width: width }">\n    &lt;input type=&quot;text&quot; :style=&quot;styleObj&quot; :readonly=&quot;readonly&quot; v-model=&quot;showValue&quot; @click=&quot;show = !show&quot;&gt;\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              &lt;span class=&quot;btn-prev&quot; @click=&quot;yearClick(-1)&quot;&gt;&lt;</span>\n              <span class="show-year">{{ now.getFullYear() }}</span>\n              &lt;span class=&quot;btn-next&quot; @click=&quot;yearClick(1)&quot;&gt;&gt;</span>\n            </th>\n            <th colspan="3">\n              &lt;span class=&quot;btn-prev&quot; @click=&quot;monthClick(-1)&quot;&gt;&lt;</span>\n              <span class="show-month">{{ months[now.getMonth()] }}</span>\n              &lt;span class=&quot;btn-next&quot; @click=&quot;monthClick(1)&quot;&gt;&gt;</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            &lt;td v-for=&quot;j in 7&quot; :key=&quot;j&quot; :class=&quot;date[i * 7 + j] &amp;&amp; date[i * 7 + j].status&quot;\n              :date=&quot;date[i * 7 + j] &amp;&amp; date[i * 7 + j].date&quot; @click=&quot;pickDate(i * 7 + j)&quot;&gt;{{ date[i * 7 + j] &amp;&amp; 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 &amp;&amp; (curFirstDay = 7)\n      time.setDate(0)                             // the last day\n      var lastDayCount = time.getDate()\n      for (let i = curFirstDay; i &gt; 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 &lt; curDayCount; i++) {\n        let tmpTime = new Date(time.getFullYear(), time.getMonth(), i + 1)\n        let status = ''\n        this.stringify(tmpTime) === value &amp;&amp; (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 &lt; 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: &quot;Segoe UI&quot;, &quot;Lucida Grande&quot;, Helvetica, Arial, &quot;Microsoft YaHei&quot;;\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>
Vue 日期选择器组件 - 简洁易用, 可自定义样式

原文地址: https://www.cveoy.top/t/topic/pyYj 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录