Heim > Web-Frontend > js-Tutorial > Hauptteil

So verwenden Sie den Datepicker

php中世界最好的语言
Freigeben: 2018-03-23 13:36:26
Original
4656 Leute haben es durchsucht

Dieses Mal zeige ich Ihnen, wie Sie Datepicker verwenden und welche Vorsichtsmaßnahmen bei der Verwendung von Datepicker gelten. Das Folgende ist ein praktischer Fall, schauen wir uns das an.

Vorwort

Das Schreiben von Plug-Ins ist sehr interessant und sehr herausfordernd, da dabei viele Details entdeckt werden können. Im Prozess der Front-End-Entwicklung ist jQuery zweifellos ein wichtiger Meilenstein. Rund um dieses hervorragende Projekt sind viele hervorragende Plug-Ins entstanden, die direkt verwendet werden können, was Entwicklern viel Zeit spart. Die wichtigste Rolle von jQuery ist die browserübergreifende Nutzung Front-End-Frameworks als Ersatz für jQuery. Ich persönlich bevorzuge Vue js, daher möchte ich versuchen, eine Komponente mit Vue.js zu schreiben.

Um auf npm zu veröffentlichen, habe ich den Namen der Projektadresse geändert, aber der interne Code wurde nicht geändert und die Verwendung ist bequemer als zuvor.

GitHub-Adresse: Hier

Funktionen & Erwartungen

Dieser Datepicker implementiert derzeit nur einige allgemeine Funktionen:

  1. Zeit auswählen (This ist etwas überflüssig)

  2. Maximales/minimales Zeitlimit

  3. Chinesisch/Englisch-Umstellung (eigentlich müssen nur die Woche und der Monat umgestellt werden )

  4. kann im .vue-Format oder direkt in der Browserumgebung verwendet werden

  5. Nicht mehr. . .

Verzeichnisstruktur

Der erste Schritt besteht immer noch darin, ein Projekt zu erstellen, das nur aus einer einzelnen Komponente besteht und die Die Struktur ist nicht kompliziert. Datepicker.vue ist die wichtigste Komponentendatei, dist ist der Ausgabeordner von Webpack, index.js ist die von Webpack gepackte Eintragsdatei und schließlich wird die Webpack-Konfigurationsdatei verwendet Ändern Sie unsere Bibliotheksdateien zum Verpacken. Die Projektstruktur ist also wie folgt:

.
├── Datepicker.vue
├── LICENSE
├── README.md
├── dist
│ └── vue-datepicker.js
├── index.js
├── package.json
└── webpack.config.js
Nach dem Login kopieren

Beginnen Sie mit Datepicker.vue

Das Schreiben von Vue-Komponenten in .vue ist eine besondere Art des Schreibens. Jede Vue-Datei enthält eine Vorlage, ein Skript und einen Stil In den drei Teilen ist es am besten, die Vorlage nicht als Fragmentinstanz zu verwenden, sodass die äußerste Schicht zunächst mit einer p-Schicht bedeckt wird, die als Wurzelelement der gesamten Komponente verwendet wird. Ein Datumswähler besteht im Allgemeinen aus zwei Teilen: einem Eingabefeld zur Anzeige des Datums und einem Bedienfeld zur Auswahl des Datums. Da ich festgestellt habe, dass die Eingabe automatisch die Tastatur auf dem mobilen Endgerät hervorruft, habe ich die Eingabe nicht verwendet und direkt p verwendet Simulation, durch Klicken auf Das Ereignis bestimmt die Sichtbarkeit des Panels. Der Wert ist das Endergebnis und muss mit der übergeordneten Komponente kommunizieren. Daher wird der Wert als prop geschrieben und value.sync="xxx" wird in der übergeordneten Komponente verwendet. Der Wert des Datepickers ist bidirektional an xxx des gebunden übergeordnete Komponente.

<template>
 <p class="date-picker">
  <p class="input" v-text="value" @click="panelState = !panelState">
 </p>
 <p class="date-panel" v-show="panelState">
 </p>
</template>
<scrip>
 export default {
  data () {
   return {
    panelState: false //初始值,默认panel关闭
   }
  },
  props: {
   value: String
  }
 }
</script>
Nach dem Login kopieren

Renderdatumsliste

Ein Monat hat mindestens 28 Tage. Wenn der Sonntag am Anfang festgelegt ist, werden mindestens 4 Zeilen benötigt (die 1. ist zufällig der Sonntag). aber jeder Die Anzahl der Tage im Monat beträgt meistens 30 oder 31, und der 1. ist nicht unbedingt Sonntag, daher habe ich ihn einfach entsprechend der häufigsten Situation entworfen, mit insgesamt 6 Zeilen Die Orte, die nicht ausgefüllt sind Die Daten des aktuellen Monats werden mit den Daten des Vormonats oder des Folgemonats gefüllt, was die Berechnung erleichtert und die Panelhöhe ändert sich beim Monatswechsel nicht. Das Array von Datumslisten muss dynamisch berechnet werden. Vue stellt das berechnete Attribut bereit, sodass die Datumsliste dateList direkt als berechnetes Attribut geschrieben wird. Meine Methode besteht darin, die Datumsliste in einem Array mit einer Länge von 42 zu fixieren und sie dann nacheinander mit den Daten dieses Monats, des letzten Monats und des nächsten Monats zu füllen.

computed: {
 dateList () {
  //获取当月的天数
  let currentMonthLength = new Date(this.tmpMonth, this.tmpMonth + 1, 0).getDate()
  //先将当月的日期塞入dateList
  let dateList = Array.from({length: currentMonthLength}, (val, index) => {
   return {
    currentMonth: true,
    value: index + 1
   }
  })
  //获取当月1号的星期是为了确定在1号前需要插多少天
  let startDay = new Date(this.year, this.tmpMonth, 1).getDay()
  //确认上个月一共多少天
  let previousMongthLength = new Date(this.year, this.tmpMonth, 0).getDate()
 }
 //在1号前插入上个月日期
 for(let i = 0, len = startDay; i < len; i++){
  dateList = [{previousMonth: true, value: previousMongthLength - i}].concat(dateList)
 }
 //补全剩余位置
 for(let i = 0, item = 1; i < 42; i++, item++){
  dateList[dateList.length] = {nextMonth: true, value: i}
 }
 return dateList
}
Nach dem Login kopieren

Hier verwenden wir Array.from, um ein Array zu initialisieren, übergeben ein Array Like, konvertieren es in ein Array und verwenden arr[arr.length] und [{}].concat beim Spleißen von Zeichenfolgen . (arr) Da ich bei JsTips erfahren habe, dass sie auf diese Weise eine bessere Leistung erbringt, werden relevante Links am Ende des Artikels veröffentlicht.
Auf diese Weise wird die Datumsliste erstellt und mithilfe einer V-for-Schleife in der Vorlage gerendert.

<ul class="date-list">
 <li v-for="item in dateList"
  v-text="item.value" 
  :class="{preMonth: item.previousMonth, nextMonth: item.nextMonth,
   selected: date === item.value && month === tmpMonth && item.currentMonth, invalid: validateDate(item)}"
  @click="selectDate(item)">
 </li>
</ul>
Nach dem Login kopieren

Sie können Ihren eigenen Stil verwenden, um zu schreiben, was Sie möchten. Es ist zu beachten, dass das Zyklusdatum im letzten Monat oder in diesem Monat angezeigt werden kann. Ich habe es durch previuosMonth, currentMonth und nextMonth markiert, um Beurteilungsbedingungen für andere Funktionen bereitzustellen.
Die Jahres- und Monatslisten sind ähnlich. Ich habe den Anfangswert der Jahresliste direkt in die Daten geschrieben, wobei das aktuelle Jahr der erste ist. Um mit dem Monat übereinzustimmen, werden jeweils 12 angezeigt -zum Rendern.

data () {
 return {
  yearList: Array.from({length: 12}, (value, index) => new Date().getFullYear() + index)
 }
}
Nach dem Login kopieren

Datumsfunktion auswählen

Die Auswahlreihenfolge ist: Jahr-> Monat-> Tag, sodass wir den im Panel angezeigten Inhalt über eine Statusvariable steuern können Bindung ist geeignet Die Funktion schaltet den Anzeigezustand um.

<p>
 <p class="type-year" v-show="panelType === &#39;year&#39;">
  <ul class="year-list">
   <li v-for="item in yearList"
    v-text="item"
    :class="{selected: item === tmpYear, invalid: validateYear(item)}" 
    @click="selectYear(item)"
   >
   </li>
  </ul>
 </p>
 <p class="type-month" v-show="panelType === &#39;month&#39;">
  <ul class="month-list">
   <li v-for="item in monthList"
    v-text="item | month language"
    :class="{selected: $index === tmpMonth && year === tmpYear, invalid: validateMonth($index)}" 
    @click="selectMonth($index)"
   >
   </li>
  </ul>
 </p>
 <p class="type-date" v-show="panelType === &#39;date&#39;">
  <ul class="date-list">
   <li v-for="item in dateList"
    v-text="item.value" 
    track-by="$index" 
    :class="{preMonth: item.previousMonth, nextMonth: item.nextMonth,
     selected: date === item.value && month === tmpMonth && item.currentMonth, invalid: validateDate(item)}"
    @click="selectDate(item)">
   </li>
  </ul>
 </p>
</p>
Nach dem Login kopieren

选择日期的方法就不细说了,在selectYear,selectMonth中对年份,月份变量赋值,再分别将panelType推向下一步就实现了日期选择功能。

不过在未选择完日期之前,你可能不希望当前年月的真实值发生变化,所以在这些方法中可先将选择的值赋给一个临时变量,等到seletDate的时候再一次性全部赋值。

selectMonth (month) {
 if(this.validateMonth(month)){
  return
 }else{
  //临时变量
  this.tmpMonth = month
  //切换panel状态
  this.panelType = 'date'
 }
},
selectDate (date) {
 //validate logic above...
 //一次性全部赋值
 this.year = tmpYear
 this.month = tmpMonth
 this.date = date.value
 this.value = `${this.tmpYear}-${('0' + (this.month + 1)).slice(-2)}-${('0' + this.date).slice(-2)}`
 //选择完日期后,panel自动隐藏
 this.panelState = false
}
Nach dem Login kopieren

最大/小时间限制

最大/小值是需要从父组件传递下来的,因此应该使用props,另外,这个值可以是字符串,也应该可以是变量(比如同时存在两个datepicker,第二个的日期不能比第一个大这种逻辑),所以应该使用Dynamically bind的方式传值。

<datepicker :value.sync="start"></datepicker>
<!-- 现在min的值会随着start的变化而变化 -->
<datepicker :value.sync="end" :min="start" ></datepicker>
Nach dem Login kopieren

增加了限制条件,对于不合法的日期,其按钮应该变为置灰状态,我用了比较时间戳的方式来判断日期是否合法,因为就算当前panel中的日期是跨年或是跨月的,通过日期构造函数创建时都会帮你转换成对应的合法值,省去很多判断的麻烦:

new Date(2015, 0, 0).getTime() === new Date(2014, 11, 31).getTime() //true
new Date(2015, 12, 0).getTime() === new Date(2016, 0, 0).getTime() //true
Nach dem Login kopieren

因此验证日期是否合法的函数是这样的:

validateDate (date) {
 let mon = this.tmpMonth
 if(date.previousMonth){
  mon -= 1
 }else if(date.nextMonth){
  mon += 1
 }
 if(new Date(this.tmpYear, mon, date.value).getTime() >= new Date(this.minYear, this.minMonth - 1, this.minDate).getTime()
  && new Date(this.tmpYear, mon, date.value).getTime() <= new Date(this.maxYear, this.maxMonth - 1, this.maxDate).getTime()){
  return false
 }
 return true
}
Nach dem Login kopieren

动态计算位置

当页面右侧有足够的空间显示时,datepicker的panel会定位为相对于父元素left: 0的位置,如果没有足够的空间,则应该置于right: 0的位置,这一点可以通过Vue提供的动态样式和样式对象来实现(动态class和动态style其实只是动态props的特例),而计算位置的时刻,我放在了组件声明周期的ready周期中,因为这时组件已经插入到DOM树中,可以获取style进行动态计算:

ready () {
 if(this.$el.parentNode.offsetWidth + this.$el.parentNode.offsetLeft - this.$el.offsetLeft <= 300){
  this.coordinates = {right: &#39;0&#39;, top: `${window.getComputedStyle(this.$el.children[0]).offsetHeight + 4}px`}
 }else{
  this.coordinates = {left: &#39;0&#39;, top: `${window.getComputedStyle(this.$el.children[0]).offsetHeight + 4}px`}
 }
}
<!-- template中对应的动态style -->
<p :style="coordinates"></p>
Nach dem Login kopieren

为了panel的显隐可以平滑过渡,可以使用transition做过渡动画,这里我简单地通过一个0.2秒的透明度过渡让显隐更平滑。

<p :style="this.coordinates" v-show="panelState" transition="toggle"></p>
//less syntax
.toggle{
 &-transition{
  transition: all ease .2s;
 }
 &-enter, &-leave{
  opacity: 0;
 }
}
Nach dem Login kopieren

中英文切换

这里其实也很简单,这种多语言切换实质就是一个key根据不同的type而输出不同的value,所以使用filter可以很容易的实现它!比如渲染星期的列表:

<ul class="weeks">
  <li v-for="item in weekList" v-text="item | week language"></li>
 </ul>
 
filters : {
 week (item, lang){
  switch (lang) {
   case 'en':
    return {0: 'Su', 1: 'Mo', 2: 'Tu', 3: 'We', 4: 'Th', 5: 'Fr', 6: 'Sa'}[item]
   case 'ch':
    return {0: '日', 1: '一', 2: '二', 3: '三', 4: '四', 5: '五', 6: '六'}[item]
   default:
    return item
  }
 }
}
Nach dem Login kopieren

多种使用方式

对于一个Vue组件,如果是使用webpack + vue-loader的.vue单文件写法,我希望这样使用:

//App.vue
<script>
 import datepicker from 'path/to/datepicker.vue'
 export default {
  components: { datepicker}
 }
</script>
Nach dem Login kopieren

如果是直接在浏览器中使用,那么我希望datepicker这个组件是暴露在全局下的,可以这么使用:

//index.html
<html>
 <script src="path/to/vue.js"></script>
 <script src="path/to/datepicker.js"></script>
 <body>
  <p id="app"></p>
  <script>
   new Vue({
    el: '#app',
    components: { datepicker }
   })
  </script>
 </body>
</html>
Nach dem Login kopieren

这里我选择了webpack作为打包工具,使用webpack的output.library和output.linraryTarget这两个属性就可以把你的bundle文件作为库文件打包。library定义了库的名字,libraryTarget定义了你想要打包的格式,具体可以看文档。我希望自己的库可以通过datepicker加载到,并且打包成umd格式,因此我的webpack.config.js是这样的:

module.exports = {
 entry: './index.js',
 output: {
  path: './dist',
  library: 'datepicker',
  filename: 'vue-datepicker.js',
  libraryTarget: 'umd'
 },
 module: {
  loaders: [
   {test: /\.vue$/, loaders: ['vue']},
   {test: /\.js$/, exclude: /node_modules/, loaders: ['babel']}
  ]
 }
}
Nach dem Login kopieren

打包完成的模块就是一个umd格式的模块啦,可以在浏览器中直接使用,也可以配合require.js等模块加载器使用!

适配 Vue 2.x

Vue 2.0已经发布有段时间了,现在把之前的组件适配到Vue 2.0。迁移过程还是很顺利的,核心API改动不大,可以借助vue-migration-helper来找出废弃的API再逐步修改。这里只列举一些我需要修改的API。

filter

2.0中的filter只能在mustache绑定中使用,如果想在指令式绑定中绑定过滤后的值,可以选择计算属性。我在月份和星期的显示中使用到了过滤器来过滤语言类型,但我之前是在指令式绑定中使用的filter,所以需要如下修改,:

//修改前
<p class="month-box" @click="chType(&#39;month&#39;)" v-text="tmpMonth + 1 | month language"></p>
//修改后,filter传参的方式也变了,变成了函数调用的风格
<p class="month-box" @click="chType(&#39;month&#39;)">{{tmpMonth + 1 | month(language)}}</p>
Nach dem Login kopieren

移除$index和$key

这两个属性不会在v-for中被自动创建了,如需使用,要在v-for中自行声明:

<li v-for="item in monthList" @click="selectMonth($index)"></li>
//
<li v-for="(item, index) in monthList" @click="selectMonth(index)"></li>
Nach dem Login kopieren

ready 生命周期移除

ready从生命周期钩子中移除了,迁移方法很简单,使用mounted和this.$nextTick来替换。

prop.sync弃用

prop的sync弃用了,迁移方案是使用自定义事件,而且Datepicker这种input类型组件,可以使用表单输入组件的自定义事件作为替换方案。自定义组件也可以使用v-model指令了,但是必须满足两个条件:

  1. 接收一个value的prop

  2. 值发生变化时,触发一个input事件,传入新值。

所以Datepicker的使用方式也不是了,而是。组件自身向父级传值的方式也不一样了:

//1.x版本,设置了value的值会同步到父级
this.value = `${this.tmpYear}-${('0' + (this.month + 1)).slice(-2)}-${('0' + this.date).slice(-2)}`
//2.x版本,需要自己触发input事件,将新值作为参数传递回去
let value = `${this.tmpYear}-${('0' + (this.month + 1)).slice(-2)}-${('0' + this.date).slice(-2)}`
this.$emit('input', value)
Nach dem Login kopieren

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

datepicker插件监听输入框

NavigatorIOS组件的使用详解

ejsExcel模板在Vue.js中的使用

Das obige ist der detaillierte Inhalt vonSo verwenden Sie den Datepicker. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage