這篇文章主要介紹了關於淺談Vue 數據響應式原理,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
前言
Vue的資料回應主要是依賴了Object.defineProperty(),那麼整個過程是怎麼樣的呢?以我們自己的想法來走Vue的道路,其實也就是以Vue的原理為終點,我們來逆推一下實現過程。
本文程式碼皆為低配版本,很多地方都不嚴謹,例如if(typeof obj === 'object')這是在判斷obj是否為一個對象,雖然obj也有可能是數組等其他類型的數據,但是本文為了簡便,就直接這樣寫來表示判斷對象,對於數組使用Array.isArray()。
改造資料
我們先來嘗試寫一個函數,用來改造物件:
為什麼要先寫這個函數呢?因為改造資料是一個最基礎也是最重要的步驟,之後所有的步驟都會依賴這一步。
// 代码 1.1 function defineReactive (obj,key,val) { Object.defineProperty(obj,key,{ enumerable: true, configurable: true, get: function () { return val; }, set: function (newVal) { //判断新值与旧值是否相等 //判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身 if(newVal === val || (newVal !== newVal && value !== value)){ return ; } val = newVal; } }); }
例如const obj = {},然後再呼叫defineReactive(obj,'a',2)方法,此時在函數內,val=2 ,然後每次取得obj.a的值的時候都是取得val的值,設定obj.a的時候也是設定val的值。 (每次呼叫defineReactive都會產生一個閉包保存了val的值);
#流程討論
經過驗證之後,發現這個函數確實可以使用的。然後我們來討論一下回應的流程:
輸入資料
改造資料(defineReactive() )
如果資料變動=> 觸發事件
#我們來看第三步,資料變動如何觸發之後的事件呢?仔細思考一下,如果要改變數據,那就必須先set數據,那我們直接set()裡面加入方法就ok了呀。
然後還有一個重要問題:
#依賴收集
- 我們怎麼知道資料改變之後要觸發的是什麼事件呢?在Vue中: 使用資料=> 視圖; 使用了資料來渲染視圖,那麼在取得資料的時候收集依賴是最佳的時機,Vue在改造資料屬性的時候產生一個Dep實例,用於收集依賴。
// 代码 1.2 class Dep { constructor(){ //订阅的信息 this.subs = []; } addSub(sub){ this.subs.push(sub); } removeSub (sub) { remove(this.subs, sub); } //此方法的作用等同于 this.subs.push(Watcher); depend(){ if (Dep.target) { Dep.target.addDep(this); } } //这个方法就是发布通知了 告诉你 有改变啦 notify(){ const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update(); } } } Dep.target = null;
程式碼1.2就是Dep的部分程式碼,暫時只需要知道2個方法的作用就可以了
depend() --- 可以理解為收集依賴的事件,不考慮其他方面的話功能等同於addSub()
notify() --- 這個方法更為直觀了,執行所有依賴的update()方法。就是之後的改變視圖啊 等等。
本篇主要討論資料回應的過程,不深入討論 Watcher類,所以Dep中的方法知道作用就可以了。
然後就是改變程式碼1.1了- 這程式碼中有一個疑點,Dep.target是什麼?為什麼要有Dep.target才會收集依賴呢?
- Dep是一個類,Dep.target是類別的屬性,並不是dep實例的屬性。
//代码 1.3 function defineReactive (obj,key,val) { const dep = new Dep(); Object.defineProperty(obj,key,{ enumerable: true, configurable: true, get: function () { if(Dep.target){ //收集依赖 等同于 dep.addSub(Dep.target) dep.depend() } return val; }, set: function (newVal) { if(newVal === val || (newVal !== newVal && val !== val)){ return ; } val = newVal; //发布改变 dep.notify(); } }); }
Dep類別在全域可用,所以Dep.target在全域能存取到,可以任意改變它的值。
get這個方法使用很平常,不可能每次使用取得資料值的時候都去呼叫dep.depend()。dep.depend()其實就是dep.addSub(Dep.target)。
那麼最好方法就是,在使用之前把Dep.target設定成某個對象,在訂閱完成之後設定Dep.target = null。
驗證
#是時候來驗證一波程式碼的可用性了
#
//代码 1.4 const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}}; //低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了) const watcher = { addDep:function (dep) { dep.addSub(this); }, update:function(){ html(); } } //假装这个是渲染页面的 function html () { document.querySelector('body').innerHTML = obj.html; } defineReactive(obj,'html','how are you');//定义响应式的数据 Dep.target = watcher; html();//第一次渲染界面 Dep.target = null;

此時瀏覽器上的介面是這樣的
#然後在下開啟了控制台開始調試,輸入:######obj.html = 'I am fine thank you'#########然後就發現,按下回車的那一瞬間,奇蹟發生了,頁面變成了######## #############結尾############Vue資料回應的設計模式和訂閱發布模式有一點像,但是不同,每一個dep實例就是一個訂閱中心,每次發布都會把所有的訂閱全部發佈出去。 ###
Vue的響應式原理其實還有很大一部分,本文主要討論了Vue是如何讓數據進行響應,但是實際上,一般的數據都是很多的,一個數據被多處使用,改變數據之後觀察新價值,如何觀察、如何訂閱、如何調度,都還有很大一部分沒有討論。主要的三個類別Dep(收集依賴)、Observer(觀察資料)、Watcher(訂閱者,若資料有變化通知訂閱者),都只提了一點點。
之前寫有一篇Vue響應式----陣列變異方法,針對Vue中對陣列的改造進行討論。當然之後有更多其他的文章,整個資料回應流程還有很多內容,三個主要的類別都還沒討論完。
其實閱讀原始碼不只是為了知道原始碼是如何運作的,更重要的是學習作者的想法與方法,我寫的文章都不長,希望自己能夠每次專注於一個點,能夠真真實實領悟到這一點的原理。當然也想控制閱讀時間,免得大家看到一半就關閉了。
相關推薦:
#
以上是淺談Vue 資料響應式原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版
中文版,非常好用