【前端100問】Q23:聊聊 Redux 和 Vuex 的設計思想

寫在前面

此系列來源于開源項目:前端 100 問:能搞懂 80%的請把簡歷給我
為了備戰(zhàn) 2021 春招
每天一題嗅钻,督促自己
從多方面多角度總結答案皂冰,豐富知識
聊聊 Redux 和 Vuex 的設計思想
簡書整合地址:前端 100 問

正文回答

在軟件開發(fā)里店展,有些通用的思想,比如隔離變化秃流,約定優(yōu)于配置等赂蕴,隔離變化就是說做好抽象,把一些容易變化的地方找到共性舶胀,隔離出來概说,不要去影響其他的代碼。約定優(yōu)于配置就是很多東西我們不一定要寫一大堆的配置嚣伐,比如我們幾個人約定糖赔,view 文件夾里只能放視圖,不能放過濾器轩端,過濾器必須放到 filter 文件夾里放典,那這就是一種約定,約定好之后船万,我們就不用寫一大堆配置文件了刻撒,我們要找所有的視圖,直接從 view 文件夾里找就行耿导。

根據(jù)這些思想声怔,對于狀態(tài)管理的解決思路就是:把組件之間需要共享的狀態(tài)抽取出來,遵循特定的約定舱呻,統(tǒng)一來管理醋火,讓狀態(tài)的變化可以預測。

Store 模式

最簡單的處理就是把狀態(tài)存到一個外部變量里面箱吕,比如:this.$root.$data芥驳,當然也可以是一個全局變量。但是這樣有一個問題茬高,就是數(shù)據(jù)改變后兆旬,不會留下變更過的記錄,這樣不利于調(diào)試

所以我們稍微搞得復雜一點怎栽,用一個簡單的 Store 模式

var store = {
  state: {
    message: "Hello!",
  },
  setMessageAction(newValue) {
    // 發(fā)生改變記錄點日志啥的
    this.state.message = newValue;
  },
  clearMessageAction() {
    this.state.message = "";
  },
};

store 的 state 來存數(shù)據(jù)丽猬,store 里面有一堆的 action,這些 action 來控制 state 的改變熏瞄,也就是不直接去對 state 做改變脚祟,而是通過 action 來改變,因為都走 action强饮,我們就可以知道到底改變(mutation)是如何被觸發(fā)的由桌,出現(xiàn)錯誤,也可以記錄記錄日志啥的

不過這里沒有限制組件里面不能修改 store 里面的 state,萬一組件瞎胡修改行您,不通過 action铭乾,那我們也沒法跟蹤這些修改是怎么發(fā)生的。所以就需要規(guī)定一下邑雅,組件不允許直接修改屬于 store 實例的 state片橡,組件必須通過 action 來改變 state妈经,也就是說淮野,組件里面應該執(zhí)行 action 來分發(fā) (dispatch) 事件通知 store 去改變。這樣約定的好處是吹泡,我們能夠記錄所有 store 中發(fā)生的 state 改變骤星,同時實現(xiàn)能做到記錄變更 (mutation)、保存狀態(tài)快照爆哑、歷史回滾/時光旅行的先進的調(diào)試工具洞难。

vuex

我的主要技術棧是 vuex,所以這里就寫寫 vuex揭朝,其他的參考Vuex队贱、Flux、Redux潭袱、Redux-saga柱嫌、Dva、MobX

Store

每一個 Vuex 里面有一個全局的 Store屯换,包含著應用中的狀態(tài) State编丘,這個 State 只是需要在組件中共享的數(shù)據(jù),不用放所有的 State彤悔,沒必要嘉抓。這個 State 是單一的,和 Redux 類似晕窑,所以抑片,一個應用僅會包含一個 Store 實例。單一狀態(tài)樹的好處是能夠直接地定位任一特定的狀態(tài)片段杨赤,在調(diào)試的過程中也能輕易地取得整個當前應用狀態(tài)的快照敞斋。

Vuex 通過 store 選項,把 state 注入到了整個應用中望拖,這樣子組件能通過 this.$store 訪問到 state 了渺尘。

const app = new Vue({
  el: "#app",
  // 把 store 對象提供給 “store” 選項,這可以把 store 的實例注入所有的子組件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `,
});
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count() {
      return this.$store.state.count;
    },
  },
};

State 改變说敏,View 就會跟著改變鸥跟,這個改變利用的是 Vue 的響應式機制。

Mutation

顯而易見,State 不能直接改医咨,需要通過一個約定的方式枫匾,這個方式在 Vuex 里面叫做 mutation,更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation拟淮。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)干茉。

const store = new Vuex.Store({
  state: {
    count: 1,
  },
  mutations: {
    increment(state) {
      // 變更狀態(tài)
      state.count++;
    },
  },
});

注意:mutation 都是同步事務

總的來說都是讓 View 通過某種方式觸發(fā) Store 的事件或方法很泊,Store 的事件或方法對 State 進行修改或返回一個新的 State角虫,State 改變之后,View 發(fā)生響應式改變

Action

到這里又該處理異步這塊兒了委造。mutation 是必須同步的戳鹅,這個很好理解,和之前的 reducer 類似昏兆,不同步修改的話枫虏,會很難調(diào)試,不知道改變什么時候發(fā)生爬虱,也很難確定先后順序隶债,A、B 兩個 mutation跑筝,調(diào)用順序可能是 A -> B死讹,但是最終改變 State 的結果可能是 B -> A。

對比 Redux 的中間件继蜡,Vuex 加入了 Action 這個東西來處理異步回俐,Vuex 的想法是把同步和異步拆分開,異步操作想咋搞咋搞稀并,但是不要干擾了同步操作仅颇。View 通過 store.dispatch('increment') 來觸發(fā)某個 Action,Action 里面不管執(zhí)行多少異步操作碘举,完事之后都通過 store.commit('increment') 來觸發(fā) mutation忘瓦,一個 Action 里面可以觸發(fā)多個 mutation。所以 Vuex 的 Action 類似于一個靈活好用的中間件引颈。

Vuex 把同步和異步操作通過 mutation 和 Action 來分開處理耕皮,是一種方式。但不代表是唯一的方式蝙场,還有很多方式凌停,比如就不用 Action,而是在應用內(nèi)部調(diào)用異步請求售滤,請求完畢直接 commit mutation罚拟,當然也可以台诗。

Vuex 還引入了 Getter,這個可有可無赐俗,只不過是方便計算屬性的復用拉队。

Vuex 單一狀態(tài)樹并不影響模塊化,把 State 拆了阻逮,最后組合在一起就行粱快。Vuex 引入了 Module 的概念,每個 Module 有自己的 state叔扼、mutation事哭、action、getter币励,其實就是把一個大的 Store 拆開慷蠕。

總的來看珊拼,Vuex 的方式比較清晰食呻,適合 Vue 的思想,在實際開發(fā)中也比較方便澎现。

對比 Redux

Redux: view——>actions——>reducer——>state 變化——>view 變化(同步異步一樣)

Vuex:

  • view——>commit——>mutations——>state 變化——>view 變化(同步操作)
  • view——>dispatch——>actions——>mutations——>state 變化——>view 變化(異步操作)
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仅胞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子剑辫,更是在濱河造成了極大的恐慌干旧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹蔽,死亡現(xiàn)場離奇詭異椎眯,居然都是意外死亡,警方通過查閱死者的電腦和手機胳岂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門编整,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乳丰,你說我怎么就攤上這事掌测。” “怎么了产园?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵汞斧,是天一觀的道長。 經(jīng)常有香客問我什燕,道長粘勒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任屎即,我火速辦了婚禮庙睡,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己埃撵,他們只是感情好赵颅,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暂刘,像睡著了一般饺谬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谣拣,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天募寨,我揣著相機與錄音,去河邊找鬼森缠。 笑死拔鹰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的贵涵。 我是一名探鬼主播列肢,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宾茂!你這毒婦竟也來了瓷马?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤跨晴,失蹤者是張志新(化名)和其女友劉穎欧聘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體端盆,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡怀骤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了焕妙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒋伦。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖访敌,靈堂內(nèi)的尸體忽然破棺而出凉敲,到底是詐尸還是另有隱情,我是刑警寧澤寺旺,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布爷抓,位于F島的核電站,受9級特大地震影響阻塑,放射性物質(zhì)發(fā)生泄漏蓝撇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一陈莽、第九天 我趴在偏房一處隱蔽的房頂上張望渤昌。 院中可真熱鬧虽抄,春花似錦、人聲如沸独柑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忌栅。三九已至车酣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間索绪,已是汗流浹背湖员。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瑞驱,地道東北人娘摔。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像唤反,于是被迫代替她去往敵國和親凳寺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 使用說明-Vuex 安裝 直接下載 / CDN 引用 Unpkg.com 提供了基于 NPM 的 CDN 鏈接拴袭。以...
    滿是裂縫的花卷閱讀 995評論 0 8
  • Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式读第。它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應...
    白水螺絲閱讀 4,667評論 7 61
  • 組件內(nèi)的狀態(tài)管理流程 每個組件都有自己的狀態(tài)拥刻、視圖和行為等組成部分。 state父泳,驅動應用的數(shù)據(jù)源般哼; view,以...
    表情帝3210閱讀 1,031評論 0 3
  • 目錄 組件化 組件通信 狀態(tài)管理 Vuex 是什么 Vuex 有什么特點 Vuex 解決了什么問題 什么類型的數(shù)據(jù)...
    前端小華子閱讀 1,996評論 0 16
  • state: 最底層的初始數(shù)據(jù) getters: 相當于vue的計算屬性惠窄,對state數(shù)據(jù)進行處理 蒸眠、擴展 mu...
    唯軒_443e閱讀 911評論 0 0