datepicker怎麼使用
這次帶給大家datepicker怎麼使用,使用datepicker的注意事項有哪些,下面就是實戰案例,一起來看一下。
前言
寫入外掛是很有意思,也很鍛鍊人,因為這個過程中能發現許多的細節問題。在前端發展的過程中,jQuery無疑是一個重要的里程碑,圍繞著這個優秀專案也出現了很多優秀的插件可以直接使用,大大節省了開發者們的時間。 jQuery最重要的作用是跨瀏覽器,而現在瀏覽器市場雖不完美,但已遠沒有從前那麼慘,數據驅動視圖的思想倍受歡迎,大家開始使用前端框架取代jQuery,我個人比較喜歡Vue. js,所以想試著用Vue.js寫一個元件出來。
為了發佈到npm上,所以給專案位址改名字了,但內部程式碼沒有改,使用方法比之前方便。
GitHub位址: Here
功能&期望
這個datepicker目前只實作了一些常用的功能:
選擇時間(這話說得有點多餘)
最大/最小時間限制
#中/英文切換(其實也就星期和月份需要切換)
可以.vue形式使用,也可在瀏覽器環境中直接使用
沒了。 。 。
目錄結構
萬事的第一步仍然是建立專案,只是單一元件,結構並不複雜,Datepicker.vue是最重要的元件文件,dist是webpack的輸出資料夾,index.js是webpack打包的入口檔案,最後是webpack的設定文件,用來對我們的程式庫檔案進行打包用的。因此專案結構就是這樣:
. ├── Datepicker.vue ├── LICENSE ├── README.md ├── dist │ └── vue-datepicker.js ├── index.js ├── package.json └── webpack.config.js
從Datepicker.vue入手
以.vue的方式寫Vue元件是一種特殊寫法,每個Vue檔案都包括template, script, style三部分,template最好不要成為片段實例,所以最外層先套一層p,當做整個組件的根元素。一個datepicker一般由兩部分組成,一個用來顯示日期的input框,一個用來選擇日期的panel,因為我發現input在移動端會自動喚起鍵盤,所以沒有使用input,直接用了p模擬,通過點擊事件決定panel的顯隱。 value是最終的結果,需要和父元件通信,所以將value寫成了prop,在父元件中使用value.sync="xxx",datepicker的value就和父元件的xxx雙向綁定了。
<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>
渲染日期列表
一個月最少是28天,如果把周日排在開頭,那麼最少(1號恰好是周日)需要4行,但是每個月天數30,31居多,而且1號又不一定是周日,我索性乾脆按最多的情況設計了,共6行,當月日期沒填滿的地方用上個月或下個月的日期補齊,這樣就方便計算了,切換月份時候panel高度不會改變。日期列表的陣列需要動態計算,Vue提供了computed這個屬性,所以直接將日期清單dateList寫成計算屬性。我的方法是將日期列表固定為長度為42的數組,然後將本月,上個月,下個月的日期依次填入。
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 }
這裡用Array.from來初始化了一個數組,傳入一個Array Like,轉換成數組,在拼接字串時候採用了arr[arr.length]和[{}].concat(arr )這種方式,因為在JsTips上學到這樣做性能更好,文章的最後會貼出相關連結。
這樣,日期列表就建構好了,在template中使用v-for循環渲染出來
<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>
樣式上就可以自己發揮了,怎麼喜歡怎麼寫。要注意的是循環日期可能會出現上個月或這個月的日期,我透過previuosMonth,currentMonth和nextMonth分別做了標記,對其他功能提供判斷條件。
年份和月份的列表都是差不多的道理,年份列表的初始值我直接寫在了data裡,以當前年份為第一個,為了和月份保持一致,每次顯示12個,都通過v -for渲染。
data () { return { yearList: Array.from({length: 12}, (value, index) => new Date().getFullYear() + index) } }
選擇日期功能
選擇順序是:年-> 月-> 日,所以我們可以透過一個狀態變數來控制panel中顯示的內容,綁定適合的函數切換顯示狀態。
<p> <p class="type-year" v-show="panelType === 'year'"> <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 === 'month'"> <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 === 'date'"> <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>
选择日期的方法就不细说了,在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 }
最大/小时间限制
最大/小值是需要从父组件传递下来的,因此应该使用props,另外,这个值可以是字符串,也应该可以是变量(比如同时存在两个datepicker,第二个的日期不能比第一个大这种逻辑),所以应该使用Dynamically bind的方式传值。
<datepicker :value.sync="start"></datepicker> <!-- 现在min的值会随着start的变化而变化 --> <datepicker :value.sync="end" :min="start" ></datepicker>
增加了限制条件,对于不合法的日期,其按钮应该变为置灰状态,我用了比较时间戳的方式来判断日期是否合法,因为就算当前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
因此验证日期是否合法的函数是这样的:
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 }
动态计算位置
当页面右侧有足够的空间显示时,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: '0', top: `${window.getComputedStyle(this.$el.children[0]).offsetHeight + 4}px`} }else{ this.coordinates = {left: '0', top: `${window.getComputedStyle(this.$el.children[0]).offsetHeight + 4}px`} } } <!-- template中对应的动态style --> <p :style="coordinates"></p>
为了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; } }
中英文切换
这里其实也很简单,这种多语言切换实质就是一个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 } } }
多种使用方式
对于一个Vue组件,如果是使用webpack + vue-loader的.vue单文件写法,我希望这样使用:
//App.vue <script> import datepicker from 'path/to/datepicker.vue' export default { components: { datepicker} } </script>
如果是直接在浏览器中使用,那么我希望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>
这里我选择了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']} ] } }
打包完成的模块就是一个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('month')" v-text="tmpMonth + 1 | month language"></p> //修改后,filter传参的方式也变了,变成了函数调用的风格 <p class="month-box" @click="chType('month')">{{tmpMonth + 1 | month(language)}}</p>
移除$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>
ready 生命周期移除
ready从生命周期钩子中移除了,迁移方法很简单,使用mounted和this.$nextTick来替换。
prop.sync弃用
prop的sync弃用了,迁移方案是使用自定义事件,而且Datepicker这种input类型组件,可以使用表单输入组件的自定义事件作为替换方案。自定义组件也可以使用v-model指令了,但是必须满足两个条件:
接收一个value的prop
值发生变化时,触发一个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)
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是datepicker怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

磁力連結是一種用於下載資源的連結方式,相較於傳統的下載方式更為便利和有效率。使用磁力連結可以透過點對點的方式下載資源,而不需要依賴中介伺服器。本文將介紹磁力連結的使用方法及注意事項。一、什麼是磁力連結磁力連結是一種基於P2P(Peer-to-Peer)協定的下載方式。透過磁力鏈接,使用者可以直接連接到資源的發布者,從而完成資源的共享和下載。與傳統的下載方式相比,磁

mdf檔案和mds檔案怎麼用隨著電腦科技的不斷進步,我們可以透過多種方式來儲存和共享資料。在數位媒體領域,我們經常會遇到一些特殊的文件格式。在這篇文章中,我們將討論一種常見的文件格式—mdf和mds文件,並介紹它們的使用方法。首先,我們需要了解mdf檔案和mds檔案的含義。 mdf是CD/DVD鏡像檔的副檔名,而mds檔則是mdf檔的元資料檔。

CrystalDiskMark是一款適用於硬碟的小型HDD基準測試工具,可快速測量順序和隨機讀取/寫入速度。接下來就讓小編為大家介紹一下CrystalDiskMark,以及crystaldiskmark如何使用吧~一、CrystalDiskMark介紹CrystalDiskMark是一款廣泛使用的磁碟效能測試工具,用於評估機械硬碟和固態硬碟(SSD)的讀取和寫入速度和隨機I/O性能。它是一款免費的Windows應用程序,並提供用戶友好的介面和各種測試模式來評估硬碟效能的不同方面,並被廣泛用於硬體評

foobar2000是一款能隨時收聽音樂資源的軟體,各種音樂無損音質帶給你,增強版本的音樂播放器,讓你得到更全更舒適的音樂體驗,它的設計理念是將電腦端的高級音頻播放器移植到手機上,提供更便捷高效的音樂播放體驗,介面設計簡潔明了易於使用它採用了極簡的設計風格,沒有過多的裝飾和繁瑣的操作能夠快速上手,同時還支持多種皮膚和主題,根據自己的喜好進行個性化設置,打造專屬的音樂播放器支援多種音訊格式的播放,它還支援音訊增益功能根據自己的聽力情況調整音量大小,避免過大的音量對聽力造成損害。接下來就讓小編為大

MetaMask(中文也叫小狐狸錢包)是一款免費的、廣受好評的加密錢包軟體。目前,BTCC已支援綁定MetaMask錢包,綁定後可使用MetaMask錢包進行快速登錄,儲值、買幣等,且首次綁定還可獲得20USDT體驗金。在BTCCMetaMask錢包教學中,我們將詳細介紹如何註冊和使用MetaMask,以及如何在BTCC綁定並使用小狐狸錢包。 MetaMask錢包是什麼? MetaMask小狐狸錢包擁有超過3,000萬用戶,是當今最受歡迎的加密貨幣錢包之一。它可免費使用,可作為擴充功能安裝在網絡

網易郵箱,作為中國網友廣泛使用的一種電子郵箱,一直以來以其穩定、高效的服務贏得了用戶的信賴。而網易信箱大師,則是專為手機使用者打造的信箱軟體,它大大簡化了郵件的收發流程,讓我們的郵件處理變得更加便利。那麼網易信箱大師該如何使用,具體又有哪些功能呢,下文中本站小編將為大家帶來詳細的內容介紹,希望能幫助到大家!首先,您可以在手機應用程式商店搜尋並下載網易信箱大師應用程式。在應用寶或百度手機助手中搜尋“網易郵箱大師”,然後按照提示進行安裝即可。下載安裝完成後,我們打開網易郵箱帳號並進行登錄,登入介面如下圖所示

在如今雲端儲存已成為我們日常生活和工作中不可或缺的一部分。百度網盤作為國內領先的雲端儲存服務之一,憑藉其強大的儲存功能、高效的傳輸速度以及便捷的操作體驗,贏得了廣大用戶的青睞。而且無論你是想要備份重要文件、分享資料,還是在線上觀看影片、聽取音樂,百度網盤都能滿足你的需求。但很多用戶可能對百度網盤app的具體使用方法還不了解,那麼這篇教學就將為大家詳細介紹百度網盤app如何使用,還有疑惑的用戶們就快來跟著本文詳細了解一下吧!百度雲網盤怎麼用:一、安裝首先,下載並安裝百度雲軟體時,請選擇自訂安裝選

Apple在周二推出了iOS17.4更新,為iPhone帶來了一系列新功能和修復。這次更新包含了全新的表情符號,同時歐盟用戶也能夠下載其他應用程式商店。此外,更新還加強了對iPhone安全性的控制,引入了更多的「失竊設備保護」設定選項,為用戶提供更多選擇和保障。 "iOS17.3首次引入了「失竊設備保護」功能,為用戶的敏感資料增加了額外的安全保障。當用戶不在家等熟悉地點時,該功能要求用戶首次輸入生物特徵信息,並在一小時後再次輸入資訊才能存取和更改某些數據,如修改AppleID密碼或關閉失竊設備保護功能
