摘要:看了一些關于雙向綁定的文章,現在來整理一下思路。另一邊監聽對應視圖改變就直接監聽事件。改變效果修改效果文章相關代碼已經同步到,歡迎查閱
看了一些關于雙向綁定的文章,現在來整理一下思路。
首先實現雙向綁定有三個步驟:
需要一個方法來識別哪一個的view被綁定了相應的數據
需要監視數據和view的變化
需要將所有變化傳播到綁定的對象和對應的view
為了解決第一個問題,要在對應的dom上添加相應的data-bind-
num:
為了解決第二個問題,一方面監聽數據改變,需要這樣添加一個set()方法進行監聽:
const Vue = { data: { num: 0 }, set(key, val) { this.data[key] = val } }
規定通過set(key, val)的方式來修改數據。
另一邊監聽對應視圖改變就直接監聽input事件。
為了解決第三個問題就需要用發布訂閱模式實現一個事件樞紐:
const EventHub = { callbacks: {}, on(eventName, callback){ this.callbacks[eventName] = this.callbacks[eventName] || []; this.callbacks[eventName].push(callback); }, emit(eventName, ...rest){ this.callbacks[eventName] = this.callbacks[eventName] || []; for(let i = 0; i < this.callbacks[eventName].length; i++){ this.callbacks[eventName][i].call(this,...rest); } } }
一方面將數據層的變化傳播到視圖,需要用特定名稱與dom上的屬性對應:
//觸發事件就修改視圖 eventHub.on("num:change", (val) => { $(`input[data-bind-num]`).val(val) $(`div[data-bind-num]`).text(val) }) //通過set()修改data來觸發對應的change事件 set(key, val) { this.data[key] = val EventHub.emit("num:change", val) }
將視圖層的變化傳播到數據:
$(`input[data-bind-num]`).on("input", function() { let val = $(this).val() === "" ? 0 : parseInt($(this).val()) Vue.set(key, val) })
至此雙向綁定就實現完成!但是這樣一個個寫事件名和屬性名有點蠢,優化一下
const fn = (prop_name) => { return { dataBind: `data-bind-${prop_name}`,//對應dom的data屬性名 eventName: `${prop_name}:change`//對應數據的change事件名稱 } } //給所有data綁定change事件,給所有data對應的view綁定input事件 Object.keys(Vue.data).map((key) => { //data修改改變view EventHub.on(fn(key).eventName, (val) => { $(`input[${fn(key).dataBind}]`).val(val) $(`div[${fn(key).dataBind}]`).text(val) }) //view改變data $(`input[${fn(key).dataBind}]`).on("input", function() { let val = $(this).val() === "" ? "" : parseInt($(this).val()) Vue.set(key, val) }) })
這樣實現的雙向綁定依賴于用set()來改變數據,而我們都希望通過 vm.property = value 這種方式直接來修改數據,這就需要用到Object.defineProperty()來劫持各個數據的getter,setter。
//給各個數據添加監聽器,用數據劫持替換原先的set(key,value) const Observer = { mapProp(obj) { if(!obj || typeof obj !== "object") { return } Object.keys(obj).map((key) => { this.defineReactive(obj, key, obj[key]) }) }, defineReactive(obj, key, val) { this.mapProp(val) Object.defineProperty(obj, key, { enumerable: true, // 可枚舉 configurable: false, // 不能再define get() { return val }, set(newVal) { console.log(`數據 ${key} 從${val}->${newVal}`) //當數據變化就貴觸發對應的change事件 EventHub.emit(fn(key).eventName, newVal) val = newVal } }) } }
這樣只需要調用一次Observer.mapProp(Vue.data)就會監聽所有data,原先的set()都可以用直接賦值代替。
改變data效果:
修改input效果:
文章相關代碼已經同步到Github,歡迎查閱~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95424.html
摘要:廢話不多說直接看效果圖代碼很好理解,但是在看代碼之前需要知道雙向綁定的原理其實就是基于實現的雙向綁定官方傳送門這里我們用官方的話來說方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并返回這個對象。 廢話不多說直接看效果圖 showImg(https://segmentfault.com/img/bVbiYY5?w=282&h=500); 代碼很好理解,但是在看代碼之前...
摘要:廢話不多說直接看效果圖代碼很好理解,但是在看代碼之前需要知道雙向綁定的原理其實就是基于實現的雙向綁定官方傳送門這里我們用官方的話來說方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并返回這個對象。 廢話不多說直接看效果圖 showImg(https://segmentfault.com/img/bVbiYY5?w=282&h=500); 代碼很好理解,但是在看代碼之前...
摘要:對于前端,有時候需要實現視圖層和數據層的雙向綁定例如當前流行的各種框架和類庫。為代表前端數據劫持。參考資料實現數據雙向綁定的三種方式談談中的雙向數據綁定非常簡單的雙向數據綁定框架三 對于前端,有時候需要實現視圖層和數據層的雙向綁定(two-way-binding), 例如當前流行的各種框架和類庫:Vue.js、Angular.js、React.js。 然而,他們最原始的實現方式其實都相...
摘要:下圖展示了實現雙向綁定的流程實現一個簡單的雙向綁定雙向綁定最最最初級進階版操作是非常耗時和好性能,所以在優化過程中先從操作入手。 接觸Vue有一段時間了,但是對于其雙向綁定的實現一直是似懂非懂,今天看到一篇寫的比較好的文章 傳送門1 根據原作者的指導自己也去實現了一遍簡單的 demo (本文的demo均基于Object.defineProperty 實現數據劫持,利用了對Vue.js實...
閱讀 3801·2023-01-11 11:02
閱讀 4307·2023-01-11 11:02
閱讀 3130·2023-01-11 11:02
閱讀 5238·2023-01-11 11:02
閱讀 4802·2023-01-11 11:02
閱讀 5575·2023-01-11 11:02
閱讀 5380·2023-01-11 11:02
閱讀 4080·2023-01-11 11:02