Vuex 源碼還有一些缺陷?

我看了vuex3和vuex4的源碼也輸出了文章,看到這篇時,vuex還有缺陷?看了看確實是好文,不愧是大佬寫的。文章不算長,推薦給大家看看。

點擊下方卡片關注我、加個星標
學習源碼整體架構系列、年度總結、JS基礎系列


眾所周知,Vuex 是 Flux 架構的一種實現。Flux 清晰確立了數據管理場景下各種職能單位,其主要準則有:

  1. 中心化狀態管理

  2. 狀態只能通過專門?突變?單元進行變更

  3. 應用層通過發送信號(一般稱 action),觸發變更

Vuex 也是緊緊圍繞這些準則開發的,通過?store?類提供 Flux 模式的核心功能。在滿足架構的基本要求之外,則進一步設計了許多便利的措施:

  1. 通過“模塊化”設計,隔離數據單元

  2. 提供 getter 機制,提高代碼復用性

  3. 使用?Vue.$watch?方法,實現數據流

  4. 零配置,天然整合進 Vue 環境

網上已經有很多解析的文章,沒必要贅述。本文僅就?中心化、信號機制、數據流?三個點的實現上展開,討論一下 Vuex 實現上的缺陷。

中心化

在Vuex中,store?整合了所有功能,是對外提供的主要接口,也是Flux模式下的數據管理中心。通過它,Vuex 主要對外提供了:

  • 信號相關的:?dispatch、commit

  • 偵聽器接口:?subscribe

  • state 值變更接口(替換state值,不應調用):?replaceState

  • state 模型變更接口(建議僅在按需引用場景下使用):registerModule、unregisterModule

  • 熱更新接口(HMR邏輯,不關注):hotUpdate

官方實現的 store 非常復雜,耦合了許多邏輯。簡便起見,我們刨除各種旁路邏輯,只關注Flux架構的中心化信號控制機制,可以總結出一份非常簡單的實現:

export default class Store {constructor(options) {this._state = options.state;this._mutations = options.mutations;}get state() {return this._state;}commit(type, payload) {this._mutations[type].apply(this, [this.state].concat([...payload]));}
}

這是理解 Vuex 的核心,整份代碼只有兩個邏輯:

  1. 通過_state屬性實現中心化、自包含數據中心層。

  2. 通過?dispatch?方法,回調觸發事先注冊的_mutations方法。

這份代碼有很多問題,舉例來說:

  • 使用簡單對象作為 state

  • 狀態的突變僅僅通過修改state對象屬性值實現

  • 沒有任何有效的機制,防止 state 對象被誤修改

這些設計問題,在Vuex中同樣存在,這與Vue.$watch機制有非常密切的關系(見下文),個人認為這是極其不嚴謹的。

信號機制

Vuex 提供了兩個與信號有關的接口,其源碼可簡略為:

export default class Store {...commit (_type, _payload, _options) {...const entry = this._mutations[type]this._withCommit(() => {entry.forEach(function commitIterator (handler) {handler(payload)})})this._subscribers.forEach(sub => sub(mutation, this.state))...}dispatch (_type, _payload) {...const entry = this._actions[type]return entry.length > 1? Promise.all(entry.map(handler => handler(payload))): entry[0](payload)}...
}

兩者之間的不同在于:

  1. dispatch?觸發的是?action?回調;commit?觸發的?mutation?回調。

  2. dispatch?返回 Promise;commit?無返回值。

這樣的設計意圖,主要還是職責分離,action 單元用于描述?發生了什么;mutation用于修改數據層狀態state。Vuex 用相似的接口,將兩者放置在相同的地位上,這一層接口設計其實存在弊病:

  1. action、mutation 各自需要一套type體系

  2. 允許應用層繞過action,直接?commit?mutation

  3. state 并非?immutable?的,而且在 action 中允許修改?state

雖然確實提升了便利性,但對初學者而言,可能導致如下反模式:

  • 設計了兩套無法正交的type體系

  • 造成“直接提交mutation即可”的假象,破壞了Flux的信號機制

  • 在 action 中手誤修改了 state ,而沒有友好的跟蹤機制(這一點在getter中特別嚴重)

由于沒有確切有效的機制防止錯誤,在使用Vuex的過程中,需要非常非常警惕;需要嚴謹正確地使用各種職能單元;或者以規范填補設計上的缺陷。

單向數據流

這里的數據流是指從 Vuex 的 state 到 Vue 組件的props/computed/data?等狀態單元的映射,即如何在組件中獲取state。Vuex 官方推薦使用 mapGetter、mapState 接口實現數據綁定。

mapState

該函數非常簡單,代碼邏輯可梳理為:

export const mapState = normalizeNamespace((namespace, states) => {const res = {}...normalizeMap(states).forEach(({ key, val }) => {res[key] = function mappedState() {...return typeof val === 'function' ?val.call(this, state, getters) :state[val]}})...return res
})

mapState 直接讀取 state 對象的屬性。值得注意的一點是,res[key]一般作為函數掛載在外部對象,此時函數的this指向掛載的 Vue 組件。

mapGetter

該函數同樣非常簡單,其代碼邏輯為:

export const mapGetters = normalizeNamespace((namespace, getters) => {const res = {}normalizeMap(getters).forEach(({ key, val }) => {res[key] = function mappedGetter() {...return this.$store.getters[val]}...})return res
})

mapGetter 訪問的則是組件掛載是?$store?實例的 getters 屬性。

從 state 到 getter

Vuex 的 getter屬性 與 Vue 的computed屬性在各方面的特性都非常相似,實際上,getter 正是基于 computed 實現的。其核心邏輯有:

function resetStoreVM(store, state, hot) {...store.getters = {}const wrappedGetters = store._wrappedGettersconst computed = {}// 遍歷 getter 配置,生成 computed 屬性forEachValue(wrappedGetters, (fn, key) => {computed[key] = () => fn(store)Object.defineProperty(store.getters, key, {// 獲取 vue 實例屬性get: () => store._vm[key],enumerable: true // for local getters})})// 新建 Vue 實例,專門用于監聽屬性變更store._vm = new Vue({data: {?state: state},computed})...
}

從代碼可以看出,Vuex 將整個 state 對象托管到vue實例的data屬性中,以此換取Vue的整個?watch?機制。而getter屬性正是通過返回實例的 computed 屬性實現的,這種實現方式,不可謂不精妙。問題則是:

  1. Vuex 與 Vue 深度耦合,致使不能遷移到其他環境下使用

  2. Vue 的watch機制是基于屬性讀寫函數實現的,如果直接替換根節點,會導致各種子屬性回調失效,即不可能實現immutable特性

后語

Vuex 給我最大的感覺是:便利,同樣的功能有各種不同語義的邏輯單元處理,職責分離方面做的非常好,如果嚴格遵循規范的話,確實能非常好的組織代碼;接口也很簡明易懂,對開發者非常友好。從用戶數量、影響力等方面來看,無疑是一個非常偉大的框架。這里提出來的一些觀點當然也是見仁見智的,目的不外乎拋磚引玉而已。


最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信 ruochuan12 拉你進群。


今日話題

湖南長沙互聯網據說發展還可以,所以建一個湖南人的前端交流群,歡迎湖南人進群。歡迎分享、收藏、點贊、在看我的公眾號文章~

一個愿景是幫助5年內前端人走向前列的公眾號

可加我個人微信?ruochuan12,長期交流學習

推薦閱讀

我在阿里招前端,我該怎么幫你(可進模擬面試群)

2年前端經驗,做的項目沒技術含量,怎么辦?

點擊方卡片關注我、加個星標

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》多篇,在知乎、掘金收獲超百萬閱讀。

從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。

同時,活躍在知乎@若川,掘金@若川。致力于分享前端開發經驗,愿景:幫助5年內前端人走向前列。

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

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

相關文章

三級菜單頁面布局_三級菜單的最快導航布局

三級菜單頁面布局重點 (Top highlight)When users navigate an interface, there’s a need for speed. The faster it is for them to find what they’re looking for, the more time they’ll save on their task.用戶導航界面時,需要提高速度。 他們找到所需內容…

java contains 通配符_java刪除文件支持通配符

packagecom.covics.zfh;importjava.io.File;importjava.io.FilenameFilter;/*** 實現帶*號的刪除文件*authordoudou**/public classTestDeleteFile {public static voidmain(String args[]) {boolean delFile //windows//deleteFileWithSign("E:\\fileDeleteTest\\test\\t…

「線性基」學習小結

向量空間 向量空間亦稱線性空間。 形式化的,我們定義一個向量空間\((P,V,,\cdot)\) 其中 \(P\)是一個域,\(V\)是一個非空的集合,其中的集合稱作向量,同時定義兩種運算分別為向量加法和標量乘法 一個\(P\)上的向量空間\((P,V,,\cdo…

ux體驗網站 英國_定義網站圖像時的UX注意事項

ux體驗網站 英國As the saying goes —俗話說 - “A picture is worth a thousand words.”“一張圖片勝過千言萬語。” When creating content on the web, it’s often recommended to be using high-quality imageries and making sure that the images serve its purpose …

iconfont 支持全新的彩色字體圖標

大家好,我是若川。iconfont我相信大家都用過,而現在支持全新的彩色字體圖標了。這是第二次轉載,上一次的好文是2020 前端技術發展回顧。點擊下方卡片關注我、加個星標學習源碼整體架構系列、年度總結、JS基礎系列一直以來,Web 中想…

回文算法java實現_java算法題:最長回文串

LeetCode: 給定一個包含大寫字母和小寫字母的字符串,找到通過這些字母構造成的最長的回文串。在構造過程中,請注意區分大小寫。比如"Aa"不能當做一個回文字符串。注 意:假設字符串的長度不會超過 1010。思路:利用hashset&#xff0…

Spring校驗@RequestParams和@PathVariables參數

我們在寫Rest API接口時候會用到很多的RequestParam和PathVariable進行參數的傳遞,但是在校驗的時候,不像使用RequestBody那樣的直接寫在實體類中,我們這篇文章講解一下如何去校驗這些參數。 依賴配置 要使用Java Validation API,…

出色的社區網站_《最后的我們》中出色的制作系統

出色的社區網站游戲設計分析 (GAME DESIGN ANALYSIS) The Last of Us became an instant classic the day it was released, back in 2013. At the sunset of the sixth console generation, it felt like Naughty Dog managed to raise the bar in all critical areas of game…

入坑 Electron 開發跨平臺桌面應用

?作為一個跨平臺的桌面應用開發框架,Electron 的迷人之處在于,它是建立在 Chromium 和 Node.js 之上的 —— 二位分工明確,一個負責界面,一個負責背后的邏輯,典型的「你負責貌美如花,我負責賺錢養家」。上…

Google 拼音會導致卡 Ctrl 鍵?

如果你使用 Windows 7 系統,并同時安裝了 Google 輸入法,那么 Firefox 啟動時、WoW 時一定也常遇到卡住 Ctrl 鍵的問題。 今天仔細搜索了下,傳說將輸入法中“Ctrl鍵快速定位”關閉即可,有待驗證,先記錄著…轉載于:http…

java 接口編程_JAVA面向接口編程

一、什么是面向接口編程要正確地使用Java語言進行面向對象的編程,從而提高程序的復用性,增加程序的可維護性、可擴展性,就必須是面向接口的編程。面向接口的編程就意味著:開發系統時,主體構架使用接口,接口…

不僅僅是手機,MWC現全球首例 5G NR 商用部署

近日,MWC大會在在巴塞羅那舉行,5G折疊手機和5G部署進度成為這屆大會的重點。除了華為與三星發布的折疊手機外,本屆大會另一個值得關注的要點是三星和賽靈思宣布推進5G NR 商用部署在韓國落地,這應該是全球首例 5G 新無線電 (NR) 商…

小程序 顯示細線_精心設計:高密度顯示器上的細線

小程序 顯示細線Despite the many benefits of Retina displays, there is one clear drawback that must be considered when designing for high-density screens:盡管Retina顯示器具有許多優點,但在設計高密度屏幕時仍必須考慮一個明顯的缺點: 必須避…

React 入門手冊

大家好,我是若川。推薦這篇可收藏的React入門手冊。也推薦之前一篇類似的文章《如何使用 React 和 React Hooks 創建一個天氣應用》。點擊下方卡片關注我、加個星標React 是目前為止最受歡迎的 JavaScript 框架之一,而且我相信它也是目前最好用的開發工具…

函數04 - 零基礎入門學習C語言35

第七章:函數04 讓編程改變世界 Change the world by program 上節課的練習簡單講解,給力!! 1.自己實現pow()函數并嘗試驗證…… 2.猜想下sqrt()函數的原理并嘗試編程……(暫時只要求整型數據) 3.編寫一個用來統…

java數據結構與算法_清華大學出版社-圖書詳情-《數據結構與算法分析(Java版)》...

前 言數據結構是計算機程序設計重要的理論技術基礎,它不僅是計算機學科的核心課程,而且已經成為計算機相關專業必要的選修課。其要求是學會分析、研究計算機加工的數據結構的特性,初步掌握算法的時間和空間分析技術,并能夠編寫出結…

根號 巴比倫_建立巴比倫衛生設計系統

根號 巴比倫重點 (Top highlight)In this post I’ll explain the first phase of creating our Babylon DNA, the design system for Babylon Health, and how we moved the Babylon design team from Sketch to Figma.在這篇文章中,我將解釋創建巴比倫DNA的第一階…

《Migrating to Cloud-Native Application Architectures》學習筆記之Chapter 2. Changes Needed

2019獨角獸企業重金招聘Python工程師標準>>> Cultural Change 文化變革 A great deal of the changes necessary for enterprise IT shops to adopt cloud-native architectures will not be technical at all. They will be cultural and organizational changes t…

前端,你要知道的SEO知識

大家好,我是若川。三天假期總是那么短暫,明天就要上班了。今天推薦一篇相對簡單的文章。點擊下方卡片關注我、加個星標之前有同學在前端技術分享時提到了SEO,另一同學問我SEO是什么,我當時非常詫異,作為前端應該對SEO很…

編制網站首頁的基本原則

編制網站首頁的基本原則如下: 1、編制網站首頁的超文本文檔的組織結構應清晰,條理分明,重點突出,可讀性強,盡可能吸引用戶的注意力。 2、說明文字應簡明扼要,切中要害,每項內容介紹盡可能簡單明…