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