Vue3響應式原理

關注若川視野,回復"pdf" 領取資料,回復"加群",可加群長期交流學習

本文結構

????- 關于Vue3

????- Vue2響應式原理回顧

????-?Vue3響應式方案

????-?Vue3響應式原理

????- 手寫mini版Vue3響應式

本文共計:2349字2圖

預計閱讀時間:4min30s

關于Vue3

話說,Vue3已經進行到rc4版本了,4月份beta發布的時候前端圈紅紅火火

不會吧不會吧,不會你還沒開始學吧????

整理了一些資源,現在開始學習應該還不算晚

  • vue-next倉庫[1]

  • 20200723 Vue3 官方發布的beta文檔[2]

  • Vue3 Roadmap & FAQ[3]

  • Vue3倉庫已經合并的780多個PR[4]

  • 尤大在Vue Mastery的Vue3課:Vue 3 Deep Dive with Evan You[5]

  • 202007 尤大在前端會客廳節目關于Vue3的訪談[6]

  • 202005 The process: Making Vue 3[7]

  • 202004 尤大 - 聊聊 Vue.js 3.0 Beta 官方直播[8]

  • 2018 VueConf 杭州 尤大關于Vue3的演講視頻[9]

拉到文章底部找到上述鏈接,以下正文探討一下Vue3響應式原理

Vue2 響應式原理回顧

  • 對象響應化:遍歷每個key,通過 Object.defineProperty API定義getter,setter

//?偽代碼
function?observe(){if(typeof?obj?!='object'?||?obj?==?null){return}if(Array.isArray(obj)){Object.setPrototypeOf(obj,arrayProto)}else{const?keys?=?Object.keys()for(let?i=0;i<keys.length;i++){const?key?=?keys[i]defineReactive(obj,key,obj[key])}}
}
function?defineReactive(target,?key,?val){observe(val)Object.defineProperty(obj,?key,?{get(){//?依賴收集dep.depend()return?val},set(newVal){if(newVal?!==?val){observe(newVal)val?=?newVal//?通知更新dep.notify()}}})
}
  • 數組響應化:覆蓋數組的原型方法,增加通知變更的邏輯

//?偽代碼
const?originalProto?=?Array.prototype
const?arrayProto?=?Object.create(originalProto)
['push','pop','shift','unshift','splice','reverse','sort'].forEach(key=>{arrayProto[key]?=?function(){originalProto[key].apply(this.arguments)notifyUpdate()}
})

vue2響應式痛點

  • 遞歸,消耗大

  • 新增/刪除屬性,需要額外實現單獨的API

  • 數組,需要額外實現

  • Map Set Class等數據類型,無法響應式

  • 修改語法有限制

vue3響應式方案

使用ES6的 `Proxy`[10] 進行數據響應化,解決上述Vue2所有痛點

Proxy可以在目標對象上加一層攔截/代理,外界對目標對象的操作,都會經過這層攔截

相比 Object.defineProperty ,Proxy支持的對象操作十分全面:get、set、has、deleteProperty、ownKeys、defineProperty......等等

//?reactive?偽代碼
function?reactice(obj){return?new?Proxy(obj,{get(target,?key,?receiver){const?ret?=?Reflect.get(target,?key,?receiver)return?isObject(ret)???reactice(ret)?:?ret},set(target,?key,?val,?receiver){const?ret?=?Reflect.set(target,?key,?val,?receiver)return?ret},deleteProperty(target,?key){const?ret?=?Reflect.deleteProperty(target,?key)return?ret},})
}

Vue3響應式原理

vue3響應式原理圖
  • 通過 effect ?聲明依賴響應式數據的函數cb ( 例如視圖渲染函數render函數),并執行cb函數,執行過程中,會觸發響應式數據 getter

  • 在響應式數據 getter中進行 track依賴收集:建立 數據&cb 的映射關系存儲于 targetMap

  • 當變更響應式數據時,觸發 trigger **,**根據 targetMap 找到關聯的cb執行

  • 映射關系 targetMap 結構:

targetMap:?WeakMap{?target:Map{?key:?Set[cb1,cb2...]?}
}

手寫vue3響應式

大致結構

//?mini-vue3.js/*?建立響應式數據?*/
function?reactice(obj){}/*?聲明響應函數cb(依賴響應式數據)?*/
function?effect(cb){}/*?依賴收集:建立?數據&cb 映射關系?*/
function?track(target,key){}/*?觸發更新:根據映射關系,執行cb */
function?trigger(target,key){}

reactive

/*?建立響應式數據?*/
function?reactive(obj){//?Proxy:http://es6.ruanyifeng.com/#docs/proxy//?Proxy相當于在對象外層加攔截//?Proxy遞歸是惰性的,需要添加遞歸的邏輯//?Reflect:http://es6.ruanyifeng.com/#docs/reflect//?Reflect:用于執行對象默認操作,更規范、更友好,可以理解成操作對象的合集//?Proxy和Object的方法Reflect都有對應if(!isObject(obj))?return?objconst?observed?=?new?Proxy(obj,{get(target,?key,?receiver){const?ret?=?Reflect.get(target,?key,?receiver)console.log('getter?'+ret)//?跟蹤?收集依賴track(target,?key)return?reactive(ret)},set(target,?key,?val,?receiver){const?ret?=?Reflect.set(target,?key,?val,?receiver)console.log('setter?'+key+':'+val?+?'=>'?+?ret)//?觸發更新trigger(target,?key)return?ret},deleteProperty(target,?key){const?ret?=?Reflect.deleteProperty(target,?key)console.log('delete?'+key+':'+ret)//?觸發更新trigger(target,?key)return?ret},})return?observed
}

effect

/*?聲明響應函數cb?*/
const?effectStack?=?[]
function?effect(cb){//?對函數進行高階封裝const?rxEffect?=?function(){//?1.捕獲異常//?2.fn出棧入棧//?3.執行fntry{effectStack.push(rxEffect)return?cb()}finally{effectStack.pop()}}//?最初要執行一次,進行最初的依賴收集rxEffect()return?rxEffect
}

track

/*?依賴收集:建立?數據&cb 映射關系?*/
const?targetMap?=?new?WeakMap()
function?track(target,key){//?存入映射關系const?effectFn?=?effectStack[effectStack.length?-?1]??//?拿出棧頂函數if(effectFn){let?depsMap?=?targetMap.get(target)if(!depsMap){depsMap?=?new?Map()targetMap.set(target,?depsMap)}let?deps?=?depsMap.get(key)if(!deps){deps?=?new?Set()depsMap.set(key,?deps)}deps.add(effectFn)}
}

trigger

/*?觸發更新:根據映射關系,執行cb */
function?trigger(target,?key){const?depsMap?=?targetMap.get(target)if(depsMap){const?deps?=?depsMap.get(key)if(deps){deps.forEach(effect=>effect())}}
}

測試demo

<!--?test.html?-->
<div?id="app">{{msg}}
</div><script?src="./mini-vue3.js"></script><script>//?定義一個響應式數據const?state?=?reactive({msg:'message'})//?定義一個使用到響應式數據的?dom更新函數function?updateDom(){document.getElementById('app').innerText?=?state.msg}//?用effect聲明更新函數effect(updateDom)//?定時變更響應式數據setInterval(()=>{state.msg?=?'message'?+?Math.random()},1000)
</script>

效果:

測試效果

如果想獲取上述代碼,放在了這個倉庫:mini-vue3-reactive[11]

參考資料

[1]

vue-next倉庫: https://github.com/vuejs/vue-next

[2]

20200723 Vue3 官方發布的beta文檔: https://v3.vuejs.org/

[3]

Vue3 Roadmap & FAQ: https://github.com/vuejs/vue/projects/6

[4]

Vue3倉庫已經合并的780多個PR: https://github.com/vuejs/vue-next/pulls?q=is%3Apr+is%3Amerged

[5]

尤大在Vue Mastery的Vue3課:Vue 3 Deep Dive with Evan You: https://www.vuemastery.com/courses/vue3-deep-dive-with-evan-you/vue3-overview

[6]

202007 尤大在前端會客廳節目關于Vue3的訪談: https://www.bilibili.com/video/BV1qC4y18721

[7]

202005 The process: Making Vue 3: https://increment.com/frontend/making-vue-3/

[8]

202004 尤大 - 聊聊 Vue.js 3.0 Beta 官方直播: https://www.bilibili.com/video/BV1Tg4y1z7FH

[9]

2018 VueConf 杭州 尤大關于Vue3的演講視頻: https://www.bilibili.com/video/BV1Et41197L4

[10]

Proxy: https://es6.ruanyifeng.com/#docs/proxy

[11]

倉庫:mini-vue3-reactive: https://github.com/scarsu/mini-vue3-reactive

- END -

推薦閱讀

我在阿里招前端,我該怎么幫你?(文末有福利)
如何拿下阿里巴巴 P6 的前端 Offer
如何準備阿里P6/P7前端面試--項目經歷準備篇
大廠面試官常問的亮點,該如何做出?
如何從初級到專家(P4-P7)打破成長瓶頸和有效突破
若川知乎問答:2年前端經驗,做的項目沒什么技術含量,怎么辦?

末尾

你好,我是若川,江湖人稱菜如若川,歷時一年只寫了一個學習源碼整體架構系列~(點擊藍字了解我)

  1. 關注若川視野,回復"pdf" 領取優質前端書籍pdf,回復"加群",可加群長期交流學習

  2. 我的博客地址:https://lxchuan12.gitee.io?歡迎收藏

  3. 覺得文章不錯,可以點個在看呀^_^另外歡迎留言交流~

小提醒:若川視野公眾號面試、源碼等文章合集在菜單欄中間【源碼精選】按鈕,歡迎點擊閱讀,也可以星標我的公眾號,便于查找

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276412.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276412.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276412.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python二值化 感興趣區域_Python+OpenCV感興趣區域ROI提取方法

方法一&#xff1a;使用輪廓步驟1"""src為原圖"""ROI np.zeros(src.shape, np.uint8) #感興趣區域ROIproimage src.copy() #復制原圖"""提取輪廓"""proimagecv2.cvtColor(proimage,cv2.COLOR_BGR2GRAY) #轉換成…

error while loading shared libraries: libmysqlclient.so.16: cannot open

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_4ab24dd50100wnkv.html 問題解決辦法&#xff1a; locate libmysqlclient.so.16 如我的mysql安裝在/usr/local/mysql下&#xff0c;則結果為 /usr/local/mysql/lib/mysql/libmysqlclient.so.16 vi /etc/ld.so.conf 增…

編譯cvaux錯誤的原因

平臺vc6.0;在debug模式下編譯cvaux時會提示三個錯誤&#xff1a;error C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvGaussBG…

找準切入點,調試看源碼,事半功倍

關注若川視野&#xff0c;回復"pdf" 領取資料&#xff0c;回復"加群"&#xff0c;可加群長期交流學習最近寫了很多源碼分析相關的文章&#xff0c;React、Vue 都有&#xff0c;想把我閱讀源碼的一些心得分享給大家。React&#xff1a;React 架構的演變 - 從…

Android布局大全

Android的界面是有布局和組件協同完成的&#xff0c;布局好比是建筑里的框架&#xff0c;而組件則相當于建筑里的磚瓦。組件按照布局的要求依次排列&#xff0c;就組成了用戶所看見的界面。 所有的布局方式都可以歸類為ViewGroup的5個類別&#xff0c;即ViewGroup的5個直接子類…

java實現加減乘除運算符隨機生成十道題并判斷對錯_2020年Java面試題(3年的工作總結),最全的知識點總結...

這份Java面試題整整花了三個月的時間來整理&#xff0c;都是自己再工作中總結出來&#xff0c;記住多少就寫多少&#xff0c;希望這份資料可以幫助你們&#xff0c;文末有其余部分資料的領取方式.Redis12道面試題1.什么是Redis&#xff1f;答&#xff1a;Remote Dictionary Ser…

Linux MySQL 5.1.62 source install

源碼包官網下載&#xff1a;http://dev.mysql.com/downloads/ MySQL手冊官網下載&#xff1a;http://dev.mysql.com/doc/ 安裝ncurses&#xff1a; 1、tar -zxvf ncurses-5.9.tar.gz 2、cd ncurses-5.9.tar.gz ; ./configure; make clean; make; make install 修改時區…

RDLC 示例 文章 1

GotReportViewer的實例&#xff0c;請在下面的連接中下載&#xff1a; http://files.cnblogs.com/waxdoll/RDLC.rar http://www.databasejournal.com/features/mssql/article.php/3605826/Mastering-OLAP-Reporting--Reporting-with-Analysis-Services-KPIs.htm MSSQL Server …

.NET 中的泛型 101

1.1.1 摘要 圖1 C# 泛型介紹 在接觸泛型之前&#xff0c;我們編程一般都是使用具體類型&#xff08;char, int, string等&#xff09;或自定義類型來定義我們變量&#xff0c;如果我們有一個功能很強的接口&#xff0c;而且我們想把它提取或重構成一個通用的接口&#xff0c;使…

年底了,給想進階的的前端朋友一些福利

2020 年&#xff0c;很多朋友都經歷了一段比較艱難的求職季。年末&#xff0c;“就業寒冬”迎來了一絲暖陽&#xff0c;很多中大型互聯網公司擴大了未來一年的招聘需求。前不久&#xff0c;字節跳動放出了年末要招 1 萬人的消息&#xff0c;騰訊校招規模也將擴張至 5000 人&…

python oa系統_用python把C#操作OA的例子重寫了一下

#手工chrome.exe --remote-debugging-port9222 --user-data-dir"C:\selenum\AutomationProfile"fromselenium import webdriverfromselenium.webdriver.common.by import Byfromselenium.webdriver.support.ui import WebDriverWaitfromselenium.webdriver.chrome.op…

編譯安裝PHP出現configure: error: MySQL configure failed. Please check config.log的解決方法

以下為google的結果&#xff1a; 方案一&#xff1a; 轉載鏈接&#xff1a;http://www.php-oa.com/2008/03/28/php-make.html 好久沒有編譯安裝過php了,為了玩nginx.沒法子,編譯一次來測試.我加的編譯的參數是: # ./configure –prefix/usr/local/php –with-config-file…

[Android]?Android學習手記(二)

1。SDK源碼獲取Git這個版本控制還真是第一次聽到。Linux參考官網&#xff08;需要穿墻&#xff09;的Get source好像比較容易。Windows就比較麻煩了&#xff0c;不能通過repo方式獲取整個projects&#xff0c;只能一個獲取project。不過官網稱“The source is approximentely 2…

關于分區索引與全局索引性能比較的示例

說明&#xff1a;之前使用range分區做出來的效果不明顯&#xff0c;這次使用hash分區。 1、準備工作&#xff1a; ----創建兩張一樣的hash分區表&#xff0c;jacks_part和echos_part------------------ 1 SQL> create table jacks_part (owner varchar2(30),object_id numbe…

Vue Router 4.0 正式發布!煥然一新。

關注若川視野&#xff0c;回復"pdf" 領取資料&#xff0c;回復"加群"&#xff0c;可加群長期交流學習12月8日&#xff0c;Vue Router 4 正式發布穩定版本。在經歷了 14 個 Alpha&#xff0c;13 個 Beta 和 6 個 RC 版本之后&#xff0c;Vue Router v4 閃亮…

實戰Nginx與PHP(FastCGI)的安裝、配置與優化

轉載鏈接&#xff1a;http://ixdba.blog.51cto.com/2895551/806622 一、什么是 FastCGI FastCGI是一個可伸縮地、高速地在HTTP server和動態腳本語言間通信的接口。多數流行的HTTP server都支持FastCGI&#xff0c;包括Apache、Nginx和lighttpd等&#xff0c;同時&#xff0c;…

python在運維自動化的前景_現在學運維自動化python和大數據?

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":7,"count":7}]},"card":[{"des":"阿里云實時計算(Alibaba Cloud Realtime Com…

BOM算最尾階的損耗率 成品直接到料件

假設由B生產為A經過3道工序,各工序的損耗率分別為 C1,C2,C3; 由D生產為B經過1道工序,作業損耗率為C4. 請問在BOM中建立材料的損耗率應該是怎樣的呀? 我的理解是這樣:A的產出B的投入(1-C1)(1-C2)(1-C3)所以B的投入A的產出/(1-C1)(1-C2)(1-C3)所以建A的BOM時,材料B的損耗率為: …

10個前端8個用Vue的,怎么才能在面試中出彩?

大家好&#xff0c;我是若川。現在但凡出去面試&#xff0c;面試官幾乎必問 Vue3.0 。不僅會問一些核心特性&#xff0c;還會問原理層面的問題。比如&#xff1a;?框架層面問題&#xff1a;Vue3.0 新特性 Composition API 與 React.js 中 Hooks 的異同點&#xff1f;?源碼、原…

ASP.NET MVC學習之(5):Html.ActionLink

本文整理了該方法的幾種重載形式&#xff1a; 一 Html.ActionLink("linkText","actionName") 該重載的第一個參數是該鏈接要顯示的文字&#xff0c;第二個參數是對應的控制器的方法&#xff0c;默認控制器為當前頁面的控制器&#xff0c;如果當前頁面的控制…