1. From a small change in demand

A small page has a time field, originally in the form of HH: mm: ss (hours and minutes and seconds), now changed to just hours, not minutes. As shown below:

Take a look at the documentation and control how the components appear and the values you get when you click ok. So, if you look at the elder-UI document, there’s a value format attribute in the el-time-picker that controls the display format

2. Try the modification

Modify the previous code:

<el-time-picker is-range value-format="HH:mm:ss" V-model ="timeValue" @change="changeTime" range-separator=" to" Placeholder =" placeholder "> </el-time-picker>Copy the code

Modified code:

<el-time-picker is-range value-format="HH" v-model="timeValue" @change="changeTime" range-separator=" to" Placeholder =" placeholder "> </el-time-picker>Copy the code

After this modification, although the form of the value has changed, the following image shows only hours:

But the time popover also shows minutes and seconds:

TimePicker does not introduce the format attribute, but DatePicker does introduce the format attribute:

<el-time-picker is-range format="HH" value-format="HH" v-model="timeValue" @change="changeTime" range-separator=" to" Placeholder =" placeholder "> </el-time-picker>Copy the code

After this modification, the display effect is as follows: the column corresponding to seconds is removed, but the column corresponding to minutes remains

What the hell is going on? Look at element’s source code!

3. View the source code for time-picker in Element-UI

3.1 TimePicker source

3.1.1 The time-picker module takes the ism, which is actually the content of date-picker

Time-picker source code location: element-UI \packages\time-picker, contents as follows:

import TimePicker from '.. /date-picker/src/picker/time-picker'; /* istanbul ignore next */ TimePicker.install = function(Vue) { Vue.component(TimePicker.name, TimePicker); }; export default TimePicker;Copy the code

You can see that the time-picker actually uses the time-picker component of the date-picker. The real source code location is elder-UI \packages\date-picker\ SRC \picker\time-picker.js, which reads as follows:

import Picker from '.. /picker'; import TimePanel from '.. /panel/time'; import TimeRangePanel from '.. /panel/time-range'; export default { mixins: [Picker], name: 'ElTimePicker', props: { isRange: Boolean, arrowControl: Boolean }, data() { return { type: '' }; }, watch: { isRange(isRange) { if (this.picker) { this.unmountPicker(); this.type = isRange ? 'timerange' : 'time'; this.panel = isRange ? TimeRangePanel : TimePanel; this.mountPicker(); } else { this.type = isRange ? 'timerange' : 'time'; this.panel = isRange ? TimeRangePanel : TimePanel; } } }, created() { this.type = this.isRange ? 'timerange' : 'time'; this.panel = this.isRange ? TimeRangePanel : TimePanel; }};Copy the code

Picker, TimePanel and TimeRangePanel are introduced. So what are they? Take a look at the chart below:

One thing to note is that the Picker is mixed in here! Because we are in the daily development time mixed with a JS file, and here mixed with a Vue file.

3.1.2 Mixed usage in time-picker

Uses mixed in with element-UI:

A mix of our daily development uses:

Element UI: Element UI: element UI: element UI

The following figure shows the reference relationship between the three files in the test-page directory

Mixin.vue refers to testMixin.js and testmixin.js refers to MixinCom. The contents of the three files are very simple, as shown in the following code:

Mixins. Vue:

<template>
  <Test></Test>
</template>
<script>
import Test from './testMixin'
  export default {
    components: {Test}
  }
</script>
Copy the code

testMixin.js:

import MixinCom from './MixinCom.vue'

export default {
  mixins: [MixinCom],
  data() {
   return  {
      a: 1,
      b: 2
    }
  },
  mounted() {
    console.log('mixin',this)
  }
}
Copy the code

MixinCom.vue:

</div> </template> <script> export default {data() {return {test: "}}} </script>Copy the code

The running effect is as follows:

As for when to mix in a Vue file? What good would it do to blend in? How does VUE deal with mixing internally? Leave it to us, and leave it in the comments! Here’s a look at the source code for each of the three introduced components.

3.2 Picker source

Source location: element-UI \packages\date-picker\ SRC \picker.vue

There is a code in picker.vue:

computed: { ranged() { return this.type.indexOf('range') > -1; }},Copy the code

When we use the DatePicker component, we will pass in the type parameter, some of which have range, as shown below:

When type contains range, it represents a time range from XXX to XXX. Let’s take a look at the implementation of the template section (only the key sections remain) :

<template> <! <el-input v-if="! ranged" > </el-input> <div v-else > <! -- time --> <input> <! Separator --> <slot name="range-separator"> <span class="el-range-separator">{{rangeSeparator}}</span> </slot> <! <input> </div> </template>Copy the code

Look at the source of TimePanel below

3.3 TimePanel source

element-ui\packages\date-picker\src\panel\time.vue

Mainly look at the template section

<template> <transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')"> <div v-show="visible" class="el-time-panel el-popper" :class="popperClass"> <div class="el-time-panel__content" :class="{ 'has-seconds': showSeconds }"> <time-spinner ref="spinner" @change="handleChange" :arrow-control="useArrow" :show-seconds="showSeconds"  :am-pm-mode="amPmMode" @select-range="setSelectionRange" :date="date"> </time-spinner> </div> <div class="el-time-panel__footer"> <button type="button" class="el-time-panel__btn cancel" @click="handleCancel">{{ t('el.datepicker.cancel') }}</button> <button type="button" class="el-time-panel__btn" :class="{confirm: ! disabled}" @click="handleConfirm()">{{ t('el.datepicker.confirm') }}</button> </div> </div> </transition> </template>Copy the code

The main thing is to introduce a TimeSpinner component and define the cancel and OK buttons, which will render like this:

Here is the source code for TimeRangePanel

3.4 TimeRangePanel source

node_modules\element-ui\packages\date-picker\src\panel\time-range.vue

Let’s look at the implementation of the template part (leaving only the key parts)

<template> <transition name="el-zoom-in-top" @after-leave="$emit('dodestroy')"> <divv-show="visible"> <div class="el-time-range-picker__content"> <div class="el-time-range-picker__cell"> <! <div class="el-time-range-picker__header">{{t(' el.datepicker.starttime ')}}</div> <div> <! ShowSeconds --> <time-spinner ref="minSpinner" :show-seconds="showSeconds" :am-pm-mode="amPmMode" @change="handleMinChange" :arrow-control="arrowControl" @select-range="setMinSelectionRange" :date="minDate"> </time-spinner> </div> </div> <div class="el-time-range-picker__cell"> <! <div class="el-time-range-picker__header">{{t(' el.datepicker.endtime ')}}</div> <div> <! --> <time-spinner> </time-spinner> </div> </div> <div class="el-time-panel__footer"> <! </div> </div> </transition> </template>Copy the code

The layout is left and right, where the time-spinner component is mainly used twice (note the showSeconds property passed to the time-spinner, which is mentioned below). Time-spinne looks like this:

A final look at the time-spinner component:

3.5 TimeSpinne source

Elder-ui \packages\date-picker\ SRC \basic\time-spinner.vue (only the key parts) :

<template> <div class="el-time-spinner" :class="{ 'has-seconds': showSeconds }"> <template v-if="! arrowControl"> <! < handleClick('hours', {value: hour, disabled: disabled })" v-for="(disabled, hour) in hoursList" class="el-time-spinner__item" :key="hour" :class="{ 'active': hour === hours, 'disabled': disabled }">{{ ('0' + (amPmMode ? (hour % 12 || 12) : hour )).slice(-2) }}{{ amPm(hour) }}</li> </el-scrollbar> <! < handleClick('minutes', {value: key, disabled: false })" v-for="(enabled, key) in minutesList" :key="key" class="el-time-spinner__item" :class="{ 'active': key === minutes, disabled: ! enabled }">{{ ('0' + key).slice(-2) }}</li> </el-scrollbar> <! --> <el-scrollbar v-show="showSeconds" ref="seconds"> < li@click ="handleClick('seconds', {value: key, disabled: false })" v-for="(second, key) in 60" class="el-time-spinner__item" :class="{ 'active': key === seconds }" :key="key">{{ ('0' + key).slice(-2) }}</li> </el-scrollbar> </template> </div> </template>Copy the code

The above template code defines the hour column, minute column, and second column respectively. Note that there is a V-show =”showSeconds” on the second column as follows:

 export default {
    props: {
      showSeconds: {
        type: Boolean,
        default: true
      },
    },
 }
Copy the code

You can see that showSeconds is a property passed in from the parent component, namely from time-range.vue. Go back to time-range.vue and take a look at its definition:

export default { computed: { showSeconds() { return (this.format || '').indexOf('ss') ! = = 1; }}},Copy the code

ShowSecond is a computed property, computed by format.

data() {
  return {
    format: 'HH:mm:ss',
  };
},
Copy the code

Format is data defined in data. The default value is ‘HH:mm:ss’.

In summary, the second column can be hidden, and the minute column has no showMinute defined, so it cannot be hidden, which is why even though I pass the format and value-format attributes “HH”, the minutes are still displayed.

4. To summarize

This article from the work of using el-time picker encountered problems, a brief study of its source, but also a lot of harvest.

(1) The TimePicker component and the DatePicker component belong to the same family, so the key code is kept together. TimePicker simply brings in the parts used in the DatePicker directory;

(2) The introduction of TimePicker as a mixin has opened my eyes. It is not only possible to mix JS, but also VUE files.

(3) TimePicker is divided into two parts from the UI presentation level: picker and Panel. Panel determines whether to use TimePanel or TimeRangePanel based on whether the user passes in a type with a range.

(4) Whether TimePanel or TimeRangePanel, the final use is the time-spinner component, and this component defines three columns of time, minute and second, but can only hide the second column, not the minute column.

Just as the so-called “work with element-UI, work with hungry?”, Element-UI is a good helper of front-end VUE development, I believe you will also have experience and experience in the process of use, can say it.

If you like it, you can leave a message, like it, look at it and forward it. If you like small articles, you can also pay attention to the public number “review new knowledge” to view more content