この記事では主に Vue を使用した datepicker の作成例を紹介しますので、参考にしてください。
前書き
プラグインの作成は、その過程で多くの詳細を発見できるため、非常に興味深く、非常にトレーニングになります。フロントエンド開発のプロセスにおいて、jQuery は間違いなく重要なマイルストーンであり、この優れたプロジェクトを中心に、直接使用できる多くの優れたプラグインが登場し、開発者の時間を大幅に節約します。 jQuery の最も重要な役割はクロスブラウザーです。現在、ブラウザー市場は完全ではありませんが、データ駆動型ビューの考え方は非常に普及し始めています。個人的には Vue.js の方が好きなので、Vue.js を使ってコンポーネントを書いてみたいと思います。
npmに公開するためにプロジェクトアドレスの名前を変更しましたが、内部コードは変更されておらず、以前よりも使い勝手が良くなりました。
GitHubアドレス: こちら
機能と期待
この日付ピッカーは現在、いくつかの一般的な機能のみを実装しています:
時間を選択する(これは少し冗長です)
最大/最小時間制限
Chinese/英語の切り替え(実際には週と月だけを切り替える必要があります)
は、.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 ファイルには、テンプレート、スクリプト、スタイルの 3 つの部分が含まれています。は template のフラグメント インスタンスになるため、最初に最も外側の層が p の層で覆われ、これがコンポーネント全体のルート要素として使用されます。日付ピッカーは通常、日付を表示するための入力ボックスと日付を選択するためのパネルの 2 つの部分で構成されます。入力するとモバイル端末上のキーボードが自動的に呼び出されることがわかったので、input を使用せずに直接 p を使用しました。イベントによってパネルの表示/非表示が決まります。値は最終結果であり、親コンポーネントと通信する必要があるため、値は prop として書き込まれ、value.sync="xxx" が親コンポーネントで使用されます。日付ピッカーの値は、親コンポーネントの 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 日あり、日曜日が先頭に配置されている場合は、少なくとも 4 行が必要になります (1 日はたまたま日曜日です)。ただし、各月の日数は次のとおりです。は 30、31 が最も多く、1 日は日曜日である必要はないので、最も一般的な状況に合わせて単純に設計し、合計 6 行で今月の日付の未記入の部分を で埋めます。前月または翌月の日付を表示すると、計算が容易になり、この間はパネルの高さが変わりません。日付リストの配列は動的に計算される必要があるため、Vue は計算属性を提供するため、日付リスト 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 からこの方法の方がパフォーマンスが良いことを学んだので、関連リンクを記事の最後に掲載します。
このようにして、日付リストが構築され、テンプレート内の 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で表示される場合があるので、他の機能の判断条件を提供します。
年と月のリストは似ていますが、月との一貫性を保つために、年のリストの初期値を最初の値として、v-for を通じて毎回 12 が表示されます。与える。
data () { return { yearList: Array.from({length: 12}, (value, index) => new Date().getFullYear() + index) } }
日付関数の選択
選択順序は: 年 -> 月 -> 日であるため、状態変数を通じてパネルに表示されるコンテンツを制御し、表示状態を切り替える適切な関数をバインドできます。
<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>
日付の選択方法については詳しく説明しません。select Year と 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 を使用する必要があります。さらに、この値は文字列または変数にすることができます (たとえば、2 つの日付ピッカーがあります)。同時に、2 番目の日付は最初の日付より大きくすることはできないため (このロジック)、値を渡すには動的バインドを使用する必要があります。
<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)
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がVue の日付ピッカーのサンプル コードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター
