jQuery 等插件如果沒整合到 Vue.js ,要由外部將資料傳入到 Vue.js 會有困難,因此可透過生命週期與包裝成元件的方式,將 jQuery UI 等插件透過此方式整合到 Vue.js 使用。
1-外部的 jQuery UI 插件與 Vue.js 元件溝通的概念
可把插件/套件包裝到一個單獨的 component 裡面,畫面運算時是由 Vue.js 處理,裡面的狀態和外部的狀態要溝通時
以日期選擇器為例,是使用 jQuery UI 是可以在裡面的 DOM 來操作,雖然不建議使用 Vue.js 裡使用 DOM 的操作,但可透過將插件單獨包成一個 component 後,就可以在日期選擇器裡來操作 DOM,而不要操作插件以外的東西。
日曆插件 datepicker 點按下 confirm 後
往外傳的就會只有插件所產出的資訊。
2-透過 Vue.js 的自定元件來封裝 jQuery UI 給 Vue.js 使用
如此的話就可做到裡外的溝通,像 jQuery UI 裡就有個 <date-picker> 選日曆的方式,而這方式要如何與 Vue.js 的專案整合。
直接將 jQuery UI 的 <date-picker> 直接包裝 Vue.js 的 component
而 Vue.js 裡的 <date-picker> 元件在 DOM readey 時,在 mounted: 的生命週期時,先將插件 initialization(初始化),而 component 如果要銷毀時一定要使用 beforDestroy: 來消除。
當日期選擇時就可以到 methods: 裡的方式 update 來處理。
Vue.js 與 jQuery UI 整合 jsbin 連結
3-分析 jQuery UI Datepicker 操作 DOM 與資料操作方法
UI Datepicker 是透過 DOM readey 時,透過 <input type="text" id="datepicker"> 的元素,來將此元素初始化之後就沒事了。
https://jqueryui.com/datepicker/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>jQuery UI Datepicker - Default functionality</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <link rel="stylesheet" href="/resources/demos/style.css"> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script> $( function() { $( "#datepicker" ).datepicker(); } ); </script> </head> <body> <p>Date: <input type="text" id="datepicker"></p> </body> </html> |
以雙欄的時期選擇區間為例(https://jqueryui.com/datepicker/#date-range),點按時會有相關的對應事件。
4-整合 jQuery UI 的 Vue.js 的資料流程
(videoTime: 1:22:33)
Vue.js mounted: 之後的 $(this.$el),可以參考 mounted 官網文件連結,文件內容提到:
el 被新創建的 vm.$el 替換,並掛載到實例上去之後調用該鉤子。如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
暫列問題:
1- $(this.$el) 裡的 this.$el 是 Vue.js 的物件 ???
而在整合 jQuery UI 的 Vue.js 來說,一樣在生命週期 mounted: 時指定 Format ,也就是 dateFormat: this.dateFormat 的部份,在 onSelect: 時來做一些事情,在點按好選擇的日期後,就會印出裡面的內容出來。
onSelect: 是 jQuery UI 所提供的一個方法,也就是選擇日期點按後,透過 $emit('update-date', date) 的方式,傳往上層。
透過 $emit() 傳送上層的方式執行 Vue.js 裡的 updateDate 函式,將 onSelect 的函式 date 透過 $emit() 夾帶出來,最後傳到 Vue.js 實體資料 this.date 裡面,最後才可以由 <p>{{date}}</p> 將資料印於畫面上。
點此開新頁大圖
4-1-流程圖附記
4-1-1-Vue.js 與 jQuery UI 的初始化:
包成 Vue.js 元件於 mounted 生命週期執行函式,將函式內的 this 先以 var self 開空間放置,取得 jQuery UI 的 DOM 操作對象。
4-1-2-紅線:
4-1-2-1-jQuery 與 jQuery UI 引入環境。
4-1-2-2-透過 Vue.js 自定元件屬性 date-format='yy-mm-dd' 來初始化 jQuery UI 設定,指定時間格式 'yy-mm-dd',直接將取到的參數用於 .datepicker({}) 裡面,取代 dateFormat: self.dateFormat 變成 dateFormat: ‘yy-mm-dd’ 一樣可以使用 Vue.js 的元件。
4-1-2-3-另外在 mounted 生命週期內的 $(this.$el), this.dataFormat, 換成 $(self.$el), self.dateFormat, 使用是沒問題的,主要是使用 Vue.js mounted: 的函式層裡所取得的 this。
但在 onSelect: 裡的函式的 this 指向是 jQuery UI datepicker() 本身,如果在 onSelect: 要透過 vue.js 的 $emit() 將取得的時間資料,傳到上傳給 Vue.js 使用,就需要使用 Vue.js mounted 函式層裡的 this ( var self = this) ,透過 $emit() 將資料傳給 Vue.js 的 component,讓 Vue.js 進行後續的操作。
這部份如何驗証呢,在 onSelect: 加入 console.log('onSelectThis === self', onSelectThis === self); 比對,當點按時間選擇的動作完成,執行完 onSelect: 的函式,就會回傳 "onSelectThis === self", false。
4-1-3-綠線:
Vue.js 元件透過 jQuery UI datepicker 所取得的資料操作流程。
4-1-3-1- <date-picker date-format="yy-mm-dd"> (畫面箭頭方向畫錯,是由 vue.js 所定的 date-format 傳入時間格式 "yy-mm-dd")。
4-1-3-2-選完時間後執行函式 onSelect: ,將資料 (date) 透過 $emit() 。
4-1-4-紫線:
4-1-4-1-透過 Vue.js 的 @update-date 點按事件執行 update-date() 函式, methods: 裡的 update-date() 函式,傳給 vue.js 實體下的 data:{} 使用,裡面預先存著的 date: null 資料就更新為取得的時間資料。
4-1-5-Vue.js 畫面更新
在 Vue 的 mode 取得資料的同時,就會更新 viwe 畫面 <p>{{ date }}</p>。
4-1-6-beforeDestroy / 銷毀元件生命週期:
4-1-6-1- Vue.js beforeDestroy:
官方文件連結
文件內容提到,實例銷毀之前調用。在這一步,實例仍然完全可用。
4-1-6-2-選到 jQuery 的元素後,後方接著 .datetimepicker('hide') 與 .datepicker('destroy') 二個方法。
.datepicker('hide') – 先將日曆選擇器先不顯示 (隱藏日期時間選擇器)。
而 .datepicker('destroy') – 從元素中移除拖拽功能。
4-1-7-畫面刷新時,由 Vue.js 元件所綁定對象 ID 的不同
在畫面中如果有多個元件都用於同一個頁面,為達到元件可以各自運作,會使用不同的 ID 來操作 Vue.js 綁定對象。
5-透過 Vue.js 封裝成自訂元件後注意重點
這樣處理的好處,是如果使用三大框架 (Vue, angular, react) 就不需在使用 jQuery 的插件來開發,但有時會處理到舊專案,此時就可以將 jQuery 的插件,直接封裝成一個 component 裡來使用,讓其影響程度變小。
不要直接使用傳統做法,在 onSelect 取得資料後就直接使用插件,透過 jQuery 的 $ 直接控製與控制畫面,此時有沒有使用 Vue.js 就沒有太大的差別。
不建議這樣處理,而需要的是直接將 jQuery 對應用程式的部份降到影響最小,把選好的狀態往 Vue.js 裡的 data 傳,畫面上的 DOM <p>{{data}}</p> 就不用管了,也不可以直接操作 DOM,所有的 Vue.js 的 DOM 操作都是由 Vue.js 來完成。
資料來源
thef2e-第六關 – 旅館預約服務 – 直播主 Kuro 開發說明
Vue.js Core 30天屠龍記(第4天): Vue 實體的生命週期