Implementation Code of Date Linkage Selector Function Based on Vue Componentization

Keywords: Javascript Front-end Vue IE Firefox

Our community front-end project uses element ary component library, backstage management system uses iview, component library is very good, but the date and time selector does not have the kind of "year-month-day" linkage selection component. Although the related components given by the two component libraries are excellent, sometimes they are not very useful, and it is not clear why many component libraries have abandoned the date linkage selection. So consider doing it yourself.

 

Converting a timestamp to a date format

// Timestamp is a timestamp
new Date(timestamp)
//Obtain the object of time standard brick, such as Sun Sep 02 2018 00:00:00 GMT+0800 (China Standard Time)
/*
 Acquisition year: new Date(timestamp).getFullYear()
 Get month: new Date(timestamp).getMonth() + 1
 Get Date: new Date(timestamp).getDate() 
 Get the day of the week: new Date(timestamp).getDay() 
*/

Converting the date format (yyyy-mm-dd) to a timestamp

//Three forms
 new Date('2018-9-2').getTime()
 new Date('2018-9-2').valueOf()
 Date.parse(new Date('2018-9-2'))

Compatibility under IE

Note: The above code can't or can't get the standard time value under IE10 (including IE10 at least), because 2018-9-2 is not the standard date format (the standard is 2018-09-02), and at least the chrome kernel has done fault-tolerant processing for us (it is estimated that Firefox is compatible). Therefore, strict date string integration operations must be done, and no laziness must be allowed.

Date Online Selector Based on Vue Componentization

The purpose of the date selection component is as follows:

  • (1) Whether the current filling date is complete or default, it must pass the value to the parent component (default pass''), because the parent component needs to do relevant processing according to the acquired date value (such as restricting submission, etc.);
  • (2) Specific days should be adapted, i.e. 31 days in big month, 30 days in small month, 28 days in February and 29 days in leap year.
  • (3) If the number of days is 31 (or 30), then the number of months is selected. If the current number of months does not include the number of days selected, the number of days cleared.
  • (4) If the parent component has a time stamp, the time should be displayed for component modification.
    Implementation code (using Vue + element component library)
<template>
 <div class="date-pickers">
  <el-select 
  class="year select"
  v-model="currentDate.year"
  @change='judgeDay'
  placeholder="year">
   <el-option
   v-for="item in years"
   :key="item"
   :label="item"
   :value="item">
   </el-option>//Welcome to join the front-end stack development exchange circle to learn and exchange: 864305860
  </el-select>//Front-end personnel for 1-3 years
  <el-select //Help break through technical bottlenecks and enhance thinking ability
  class="month select"
  v-model="currentDate.month"
  @change='judgeDay'
  placeholder="month">
   <el-option
   v-for="item in months"
   :key="item"
   :label="String(item).length==1?String('0'+item):String(item)"
   :value="item">
   </el-option>
  </el-select>
  <el-select 
  class="day select"
  :class="{'error':hasError}"
  v-model="currentDate.day"
  placeholder="day">
   <el-option
   v-for="item in days"
   :key="item"
   :label="String(item).length==1?String('0'+item):String(item)"
   :value="item">
   </el-option>
  </el-select>
 </div>
</template>
<script>
export default {
 props: {
 sourceDate: {
  type: [String, Number]
 }
 },
 name: "date-pickers",
 data() {
 return {
  currentDate: {
  year: "",
  month: "",
  day: ""
  },
  maxYear: new Date().getFullYear(),
  minYear: 1910,
  years: [],
  months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
  normalMaxDays: 31,
  days: [],
  hasError: false
 };//Welcome to join the front-end stack development exchange circle to learn and exchange: 864305860
 },
 watch: {
 sourceDate() {
  if (this.sourceDate) {
  this.currentDate = this.timestampToTime(this.sourceDate);
  }
 },
 normalMaxDays() {
  this.getFullDays();
  if (this.currentDate.year && this.currentDate.day > this.normalMaxDays) {
  this.currentDate.day = "";
  }
 },
 currentDate: {
  handler(newValue, oldValue) {
  this.judgeDay();
  if (newValue.year && newValue.month && newValue.day) {
   this.hasError = false;
  } else {
   this.hasError = true;
  }
  this.emitDate();
  },
  deep: true
 }
 },
 created() {
 this.getFullYears();
 this.getFullDays();
 },//Welcome to join the front-end stack development exchange circle to learn and exchange: 864305860
 methods: {
 emitDate() {
  let timestamp; //Temporarily default to the parent component timestamp form
  if ( this.currentDate.year && this.currentDate.month && this.currentDate.day) {
   let month = this.currentDate.month < 10 ? ('0'+ this.currentDate.month):this.currentDate.month;
   let day = this.currentDate.day < 10 ? ('0'+ this.currentDate.day):this.currentDate.day;
   let dateStr = this.currentDate.year + "-" + month + "-" + day;
   timestamp = new Date(dateStr).getTime();
  } 
  else {
   timestamp = "";
  }
  this.$emit("dateSelected", timestamp);
 },
 timestampToTime(timestamp) {
  let dateObject = {};
  if (typeof timestamp == "number") {
  dateObject.year = new Date(timestamp).getFullYear();
  dateObject.month = new Date(timestamp).getMonth() + 1;
  dateObject.day = new Date(timestamp).getDate();
  return dateObject;
  }
 },
 getFullYears() {
  for (let i = this.minYear; i <= this.maxYear; i++) {
  this.years.push(i);
  }
 },
 getFullDays() {
  this.days = [];
  for (let i = 1; i <= this.normalMaxDays; i++) {
  this.days.push(i);
  }
 },
 judgeDay() {
  if ([4, 6, 9, 11].indexOf(this.currentDate.month) !== -1) {
  this.normalMaxDays = 30; //30 days in a small month
  if (this.currentDate.day && this.currentDate.day == 31) {
   this.currentDate.day = "";
  }
  } else if (this.currentDate.month == 2) {
  if (this.currentDate.year) {
   if (
   (this.currentDate.year % 4 == 0 &&
    this.currentDate.year % 100 != 0) ||
   this.currentDate.year % 400 == 0
   ) {
   this.normalMaxDays = 29; //Leap year February 29
   } else {
   this.normalMaxDays = 28; //Leap year 28 days
   }
  } 
  else {
   this.normalMaxDays = 28;//Leap year 28 days
  }
  } 
  else {
  this.normalMaxDays = 31;//31 days in the big month
  }
 }
 }
};
</script>
<style lang="less">
.date-pickers {
 .select {
 margin-right: 10px;
 width: 80px;
 text-align: center;
 }
 .year {
 width: 100px;
 }
 .error {
 .el-input__inner {
  border: 1px solid #f1403c;
  border-radius: 4px;
 }
 }
}
</style>

Code parsing
The default number of days (normal Max Days) is 31 days, the minimum year is 1910, the maximum year is the current year (because my business scenario is to fill in birthdays, you can adjust them yourself) and initialize the years and days in the create hook.

Listen for the current date

The core is to monitor every date change and correct normalMaxDays, where the current Date is deeply monitored and sent to the parent component at the same time to monitor the process:

watch: {
 currentDate: {
  handler(newValue, oldValue) {
  this.judgeDay(); //Update the current number of days
  this.emitDate(); //Send results to parent components or elsewhere
  },//Welcome to join the front-end stack development exchange circle to learn and exchange: 864305860
  deep: true
 }//Front-end personnel for 1-3 years
}//Help break through technical bottlenecks and enhance thinking ability

judgeDay method:

judgeDay() {
 if ([4, 6, 9, 11].indexOf(this.currentDate.month) !== -1) {
 this.normalMaxDays = 30; //30 days in a small month
 if (this.currentDate.day && this.currentDate.day == 31) {
  this.currentDate.day = ""; 
 }
 } else if (this.currentDate.month == 2) {
 if (this.currentDate.year) {
  if (
  (this.currentDate.year % 4 == 0 &&
   this.currentDate.year % 100 != 0) ||
  this.currentDate.year % 400 == 0
  ) {
  this.normalMaxDays = 29; //Leap year February 29
  } else {
  this.normalMaxDays = 28; //28 February of the year
  }
 } else {
  this.normalMaxDays = 28; //28 February of the year
 }
 } else {
 this.normalMaxDays = 31; //31 days in the big month
 }
}

At the beginning, I used includes to judge whether the current month is a small month: a.

if([4, 6, 9, 11].includes(this.currentDate.month))

It is also inexperienced. Finally, it is found that includes is not supported in IE10, so it is replaced by ordinary indexOf().

emitDate: 
emitDate() {
 let timestamp; //Temporarily default to the parent component timestamp form
 if ( this.currentDate.year && this.currentDate.month && this.currentDate.day) {
  let month = this.currentDate.month < 10 ? ('0'+ this.currentDate.month):this.currentDate.month;
  let day = this.currentDate.day < 10 ? ('0'+ this.currentDate.day):this.currentDate.day;
  let dateStr = this.currentDate.year + "-" + month + "-" + day;
  timestamp = new Date(dateStr).getTime();
 } //Welcome to join the front-end full stack development exchange circle, together with water blowing chat learning exchange: 864305860
 else {
  timestamp = "";
 }
 this.$emit("dateSelected", timestamp);//Relevant results sent to parent components
},

It should be noted that the above standard date format processing was not done in the beginning, because chrome has made appropriate fault tolerance, but not in IE10, so it is better to do this processing.
After the change of normalMaxDays, the number of days must be retrieved and the current number of days must be cleared as appropriate:

watch: {
 normalMaxDays() {
  this.getFullDays();
  if (this.currentDate.year && this.currentDate.day > this.normalMaxDays) {
  this.currentDate.day = "";
  }//Welcome to join the front-end full stack development exchange circle, together with water blowing chat learning exchange: 864305860
 }//Front-end personnel for 1-3 years
}//Help break through technical bottlenecks and enhance thinking ability

epilogue

Thank you for watching. If there are any shortcomings, you are welcome to criticize and correct.

Posted by kippy on Wed, 20 Mar 2019 10:36:27 -0700