Vue雙向綁定實例教程
雙向綁定簡介
我們知道Vue是一個典型的MVVM框架,Vue在動態(tài)綁定這一塊提供了豐富的API帝雇,讓我們可以用簡短的代碼寫出響應(yīng)式的效果,我們只需關(guān)注數(shù)據(jù)對象,而視圖層則通過雙向綁定的形式進(jìn)行更新春宣,以下將通過四個方面介紹雙向綁定在vue的使用及可能遇到的坑
- 雙向綁定在實際項目中的運用
- 借助Vue調(diào)試工具定位問題
- 雙向綁定與Getter/Setter器的關(guān)系,深入響應(yīng)式原理
- 綁定失敗問題的解決方案
雙向綁定在項目的實際運用
在項目中,我們對element-ui做了一次再封裝處理辉懒,以表單組件為例
在業(yè)務(wù)使用中很大的痛點在于表單各個不同組件的使用,在Jquery中,我們對不同的表單控件需要使用不同的取值形式,例如多選下拉和單選下拉玩徊、日期控件和范圍日期控件,取值邏輯不盡相同琼了,針對這種問題
我們創(chuàng)建了一個pm_form_item組件統(tǒng)一化處理 如下圖
外部通過傳入不同的參數(shù)決定控件的類型及邏輯逻锐,外部只關(guān)注綁定對象,無須關(guān)注取值設(shè)值的過程,未來拓展的過程中雕薪,假如有新的表單控件昧诱,只需增加新的參數(shù)類型,而對外部隱藏實現(xiàn).
接下來就嘗試新增一個表單組件試試吧蹦哼!
設(shè)置組件的行數(shù)鳄哭、寬度及控件類型等參數(shù)要糊,設(shè)置是否可讀,設(shè)置屬性名,這里我們期望這個控件的值綁定到formModel的createTime屬性上
觀察下效果吧纲熏!
看起來好像一切順利,現(xiàn)在我們可以進(jìn)行業(yè)務(wù)開發(fā)了
假如這是一個新增頁面锄俄,我期望在打開這個頁面的時候給這個控件一個默認(rèn)值局劲,這似乎聽起來并不難,只需要對formModel.createTime初始化值即可,如下 (created為Vue內(nèi)置生命周期函數(shù))
觀察一下現(xiàn)象
默認(rèn)值的確已經(jīng)被初始化完成,但當(dāng)我們想要再次修改控件的值時卻失敗了奶赠,這個控件現(xiàn)在對任何的輸入值都不生效鱼填。雙向綁定詭異的失敗了。下面一節(jié)將介紹Vue的調(diào)試插件定位我們遇到的這個問題.
Vue調(diào)試工具 - Vue Devtools
Vue Devtools是Vue官方出品的一款Vue的調(diào)試工具毅戈,使用是通過Chrome的插件進(jìn)行的苹丸,這里對安裝插件等準(zhǔn)備工作不做贅述
這里是Vue使用截圖
總共分為3部分 Components,Vuex,Events
Components中左側(cè)是組件樹,右側(cè)可以看到組件的data,props等苇经,這個界面可以用以監(jiān)控組件的內(nèi)部狀態(tài)赘理,是最常用的功能
Vuex是一個Vue狀態(tài)管理功能,我們可以在這里看到有關(guān)Vuex里的一些信息類似 state ,getters 等
Event界面我們可以看到Vue的事件觸發(fā),鼠標(biāo)的點擊移出移入輸入等事件扇单,都可以在這里看到
針對上述問題
我們觀察Event,每次選擇輸入值時都會觸發(fā)pick事件商模,我們可以看到我們選擇的日期也在此事件參數(shù)中
看起來似乎是因為輸入事件回調(diào)沒有正常影響對象的值,我們嘗試寫監(jiān)視器,監(jiān)聽對象的另一個屬性然后打印該變量
我們拿這個對象與正常場景下的對象進(jìn)行對比,發(fā)現(xiàn)異常場景下的對象少了createTime屬性的getter/setter方法
看起來這就是造成雙向綁定失敗問題的真兇
雙向綁定與Getter/Setter關(guān)系
在說雙向綁定與Getter/Setter器的關(guān)系時施流,我們先講一下Vue雙向綁定實現(xiàn)的基本原理
在傳統(tǒng)認(rèn)知中响疚,雙向綁定通常使用引用傳遞或類似原理完成雙向綁定,但這種方式通常會帶來非常多的問題,子組件如果可以隨意修改父組件的值,對開發(fā)人員是一個很大的心智負(fù)擔(dān)瞪醋,故在現(xiàn)代化的MVVW框架中忿晕,雙向綁定都采用類似事件通知的形式進(jìn)行。
不同于angularJs的 一處監(jiān)聽,全局檢查,Vue使用的是點對點的訂閱綁定模式,當(dāng)子組件的值發(fā)生修改時,觸發(fā)外部傳入的回調(diào)函數(shù)修改外部的值
一個雙向綁定實際的實現(xiàn)類似如下
而v-model關(guān)鍵字是對上述的一種語法糖封裝
通過上述過程我們知道Vue需要在子組件綁定值childValue發(fā)生改變時觸發(fā)回調(diào)函數(shù),所以通過賦值模式進(jìn)行改動是行不通的趟章,需要通過Set方法杏糙,在Set方法中進(jìn)行回調(diào)觸發(fā)事件調(diào)用等,類似下面的偽代碼
value{
var val;
get(){
return this.val;
}
set(newVal){
vue.$emit("parentEvent",newVal);
this.val = newVal;
}
}
這個Getter/Setter則是Vue為綁定變量動態(tài)生成的方法,Vue正是通過這種點對點的訂閱行為完成雙向綁定
綁定失敗問題的解決方案
由于我們已經(jīng)定位了問題是由于Setter/Getter問題引起,那么只要讓Vue自己能夠動態(tài)添加或我們自己手動添加即可
1.在聲明formModel的 data對象時聲明createTime屬性
2.在初始化時不使用賦值初始化蚓土,轉(zhuǎn)用Vue API
這種做法Vue會在賦值時為對象自動生成getter/setter
回顧我們第一節(jié)的內(nèi)容我們可能會有些疑問宏侍,第一次我們沒有進(jìn)行賦值操作,但我們也沒有對createTime進(jìn)行聲明或初始化getter/setter操作,但為什么結(jié)果是對的呢蜀漆?
我們嘗試在組件渲染完時谅河,打印查看createTime屬性不存在,同時也沒有g(shù)etter/setter确丢,但當(dāng)我們觸發(fā)了子組件的選擇事件后再嘗試打印
此時vue已經(jīng)為formModel對象添加了createTime和getter/setter方法绷耍,看來這個地方只是Vue為我們做了一次貼心的優(yōu)化