您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

01 vue發布訂閱模式原理(Vue的雙向數據綁定原理)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-05-08 06:47:54【】1人已围观

简介理解VUE2雙向數據綁定原理和實現1.vue雙向數據綁定是通過數據劫持結合發布訂閱模式的方式來實現的,也就是說數據和視圖同步,數據發生變化,視圖跟著變化,視圖變化,數據也隨之發生改變;2.核心:關于V

理解VUE2雙向數據綁定原理和實現

1.vue 雙向數據綁定是通過 數據劫持 結合 發布訂閱模式的方式來實現的, 也就是說數據和視圖同步,數據發生變化,視圖跟著變化,視圖變化,數據也隨之發生改變;

2.核心:關于VUE雙向數據綁定,其核心是 Object.defineProperty()方法;

3.介紹一下Object.defineProperty()方法

(1)Object.defineProperty(obj, prop, descriptor) ,這個語法內有三個參數,分別為 obj (要定義其上屬性的對象) prop (要定義或修改的屬性) descriptor (具體的改變方法)

(2)簡單地說,就是用這個方法來定義一個值。當調用時我們使用了它里面的get方法,當我們給這個屬性賦值時,又用到了它里面的set方法;

這樣我們就能實現js的雙向數據綁定,也對這個方法有初步的了解 ;

這個例子實現的效果是:隨著文本框輸入文字的變化,span中會同步顯示相同的文字內容;這樣就實現了 model => view 以及 view => model 的雙向綁定。

通過添加事件監聽keyup來觸發set方法,而set再修改了訪問器屬性的同時,也修改了dom樣式,改變了span標簽內的文本。

1.實現效果

先來看一下vue雙向數據綁定是如何進行的,以便我們確定好思考方向

2.任務拆分

拆分任務可以讓我們的思路更加清晰:

(1)將vue中的data中的內容綁定到輸入文本框和文本節點中

(2)當文本框的內容改變時,vue實例中的data也同時發生改變

(3)當data中的內容發生改變時,輸入框及文本節點的內容也發生變化

3.開始任務1——綁定內容

我們先了解一下 DocuemntFragment(碎片化文檔) 這個概念,你可以把他認為一個dom節點收容器,當你創造了10個節點,當每個節點都插入到文檔當中都會引發一次瀏覽器的回流,也就是說瀏覽器要回流10次,十分消耗資源。

而使用碎片化文檔,也就是說我把10個節點都先放入到一個容器當中,最后我再把容器直接插入到文檔就可以了!瀏覽器只回流了1次。

注意:還有一個很重要的特性是,如果使用appendChid方法將原dom樹中的節點添加到DocumentFragment中時,會刪除原來的節點。

舉個例子:

可以看到,我的app中有兩個子節點,一個元素節點,一個文本節點

但是,當我通過DocumentFragment 劫持數據一下后

注意:我的碎片化文檔是將子節點都劫持了過來,而我的id為app的div內已經沒有內容了。

同時要主要我while的判斷條件。判斷是否有子節點,因為我每次appendChild都把node中的第一個子節點劫持走了,node中就會少一個,直到沒有的時候,child也就變成了undefined,也就終止了循環。

來實現內容綁定

我們要考慮兩個問題,一個是如何綁定要input上,另一個是如何綁定要文本節點中。

這樣思路就來了,我們已經獲取到了div的所以子節點了,就在DocumentFragment里面,然后對每一個節點進行處理,看是不是有跟vm實例中有關聯的內容,如果有,修改這個節點的內容。然后重新添加入DocumentFragment中。

首先,我們寫一個處理每一個節點的函數,如果有input綁定v-model屬性或者有{ { xxx }}的文本節點出現,就進行內容替換,替換為vm實例中的data中的內容

然后,在向碎片化文檔中添加節點時,每個節點都處理一下。

創建Vue的實例化函數

效果圖如下:

我們成功將內容都綁定到了輸入框與文本節點上!

4、實現任務2——【view => model

對于此任務,我們從輸入框考慮,輸入框的問題,輸入框如何改變data。我們通過事件監聽器keyup,input等,來獲取到最新的value,然后通過Object.defineProperty將獲取的最新的value,賦值給實例vm的text,我們把vm實例中的data下的text通過Object.defineProperty設置為訪問器屬性,這樣給vm.text賦值,就觸發了set。set函數的作用一個是更新data中的text,另一個等到任務三再說。

首先實現一個響應式監聽屬性的函數。一旦有賦新值就發生變化

然后,實現一個觀察者,對于一個實例 每一個屬性值都進行觀察。

改寫編譯函數,注意由于改成了訪問器屬性,訪問的方法也產生變化,同時添加了事件監聽器,把實例的text值隨時更新

實例函數中,觀察data中的所有屬性值,注意增添了observe

最終我們改變input中的內容能改變data中的數據,單頁面卻沒有刷新

4、實現任務3——【model => view】

通過修改vm實例的屬性 該改變輸入框的內容 與 文本節點的內容。

這里涉及到一個問題 需要我們注意,當我們修改輸入框,改變了vm實例的屬性,這是1對1的。

但是,我們可能在頁面中多處用到 data中的屬性,這是1對多的。也就是說,改變1個model的值可以改變多個view中的值。

這就需要我們引入一個新的知識點:

訂閱/發布者模式

訂閱發布模式(又稱觀察者模式)定義了一種一對多的關系,讓多個觀察者同時監聽某一個主題對象,這個主題對象的狀態發生改變時就會通知所有觀察者對象。

發布者發出通知 => 主題對象收到通知并推送給訂閱者 => 訂閱者執行相應操作

1

舉個例子:

之前提到的set函數的第二個作用 就是來提醒訂閱者 進行noticy操作,告訴他們:“我的text變了!” 文本節點變成了訂閱者,接到消息后,立馬進行update操作

回顧一下,每當 new 一個 Vue,主要做了兩件事:第一個是監聽數據:observe(data),第二個是編譯 HTML:nodeToFragement(id)。

在監聽數據的過程中,我們會為 data 中的每一個屬性生成一個主題對象 dep。

在編譯 HTML 的過程中,會為每個與數據綁定相關的節點生成一個訂閱者 watcher,watcher 會將自己添加到相應屬性的 dep 容器中。

我們已經實現:修改輸入框內容 => 在事件回調函數中修改屬性值 => 觸發屬性的 set 方法。

接下來我們要實現的是:發出通知 dep.notify() => 觸發訂閱者的 update 方法 => 更新視圖。

這里的關鍵邏輯是:如何將 watcher 添加到關聯屬性的 dep 中。

注意: 我把直接賦值的操作改為了 添加一個 Watcher 訂閱者

那么,Watcher又該做些什么呢?

首先,將自己賦給了一個全局變量 Dep.target;

其次,執行了 update 方法,進而執行了 get 方法,get 的方法讀取了 vm 的訪問器屬性,從而觸發了訪問器屬性的 get 方法,get 方法中將該 watcher 添加到了對應訪問器屬性的 dep 中;

再次,獲取屬性的值,然后更新視圖。

最后,將 Dep.target 設為空。因為它是全局變量,也是 watcher 與 dep 關聯的唯一橋梁,任何時刻都必須保證 Dep.target 只有一個值。

最終我們就實現了這個雙向數據綁定功能,雖然很繁瑣,但我相信,你多打幾遍,一定會對你有所幫助,加油吧!!

聊一聊 Vue3 中響應式原理

Vue.js 3.0 "One Piece" 正式發布已經有一段時間了,真可謂是千呼萬喚始出來啊!

相比于 Vue2.x , Vue3.0 在新的版本中提供了更好的性能、更小的捆綁包體積、更好的 TypeScript 集成、用于處理大規模用例的新 API 。

在發布之前,尤大大就已經聲明了響應式方面將采用 Proxy 對于之前的 Object.defineProperty 進行改寫。其主要目的就是彌補 Object.defineProperty 自身的一些缺陷,例如無法檢測到對象屬性的新增或者刪除,不能監聽數組的變化等。

而 V

很赞哦!(57458)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:西藏日喀则吉隆县

工作室:小组

Email:[email protected]