Vue(四 Vuex)

狀態(tài)管理模式氮昧,依賴Promise
單項(xiàng)數(shù)據(jù)流


image.png

多組件共享狀態(tài)時(shí)框杜,單項(xiàng)數(shù)據(jù)流會(huì)被破壞 ===》抽取組件的共享狀態(tài)。以一個(gè)全局單例模式管理
在這種模式下袖肥,我們的組件樹構(gòu)成了一個(gè)巨大的“視圖”咪辱,不管在樹的哪個(gè)位置,任何組件都能獲取狀態(tài)或者觸發(fā)行為椎组!


image.png

1油狂、store 倉(cāng)庫(kù)
包含著你的應(yīng)用中大部分的狀態(tài) (state)。Vuex 和單純的全局對(duì)象有以下兩點(diǎn)不同:
1.1、Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的专筷。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候弱贼,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新磷蛹。

1.2吮旅、你不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation味咳。這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化鸟辅,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。
2莺葫、state
vue使用單一狀態(tài)樹匪凉,每個(gè)應(yīng)用將僅僅包含一個(gè) store 實(shí)例
Vuex 通過(guò) store 選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件“注入”到每一個(gè)子組件中(需調(diào)用 Vue.use(Vuex))

const app = new Vue({
  el: '#app',
  // 把 store 對(duì)象提供給 “store” 選項(xiàng)捺檬,這可以把 store 的實(shí)例注入所有的子組件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

mapState 輔助函數(shù)
對(duì)象展開(kāi)運(yùn)算符
3再层、getter
可以理解成store的計(jì)算屬性
4、mutation
改變store中狀態(tài)的唯一途徑就是提交mutation
必須是同步函數(shù)
可以在mutation中提交多個(gè)參數(shù)堡纬,第二個(gè)參數(shù)叫載荷payload

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
//...
store.commit('increment', {
  amount: 10
})
//對(duì)象風(fēng)格
store.commit({
  type: 'increment',
  amount: 10
})

可以 使用常量代替mutation提交類型

 mutations: {
    // 我們可以使用 ES2015 風(fēng)格的計(jì)算屬性命名功能來(lái)使用一個(gè)常量作為函數(shù)名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }

5聂受、action
類似于mutation,區(qū)別:提交的是mutation烤镐;異步

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
//接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象蛋济,所以可以commit、getter等
    increment (context) {
      context.commit('increment')
    }
  }
})

分發(fā)store.dispatch炮叶?碗旅??镜悉?祟辟?
6、module

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)

如果希望你的模塊具有更高的封裝度和復(fù)用性侣肄,你可以通過(guò)添加 namespaced: true 的方式使其成為帶命名空間的模塊旧困。
7、項(xiàng)目結(jié)構(gòu)


image.png

8稼锅、插件
8.1吼具、就是一個(gè)函數(shù),接受store作為唯一的參數(shù)

const myPlugin = store => {
  // 當(dāng) store 初始化后調(diào)用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后調(diào)用
    // mutation 的格式為 { type, payload }
  })
}
// ...
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

注意插件內(nèi)也不能直接修改store矩距,只能通過(guò)mutation來(lái)修改拗盒,
8.2、有時(shí)候插件需要獲得狀態(tài)的“快照”剩晴,比較改變的前后狀態(tài)锣咒。想要實(shí)現(xiàn)這項(xiàng)功能,你需要對(duì)狀態(tài)對(duì)象進(jìn)行深拷貝

const myPluginWithSnapshot = store => {
  let prevState = _.cloneDeep(store.state)
  store.subscribe((mutation, state) => {
    let nextState = _.cloneDeep(state)

    // 比較 prevState 和 nextState...

    // 保存狀態(tài)赞弥,用于下一次 mutation
    prevState = nextState
  })
}

生成狀態(tài)快照的插件應(yīng)該只在開(kāi)發(fā)環(huán)境中使用毅整,這一點(diǎn)個(gè)可以通過(guò)webpack來(lái)控制

const store = new Vuex.Store({
  // ...
  plugins: process.env.NODE_ENV !== 'production'
    ? [myPluginWithSnapshot]
    : []
})

8.3、logger插件绽左,日志插件用來(lái)一般的調(diào)試悼嫉,會(huì)生成狀態(tài)快照,僅在開(kāi)發(fā)環(huán)境使用

import createLogger from 'vuex/dist/logger'

const store = new Vuex.Store({
  plugins: [createLogger()]
})
//...
//幾個(gè)配置項(xiàng)
const logger = createLogger({
  collapsed: false, // 自動(dòng)展開(kāi)記錄的 mutation
  filter (mutation, stateBefore, stateAfter) {
    // 若 mutation 需要被記錄拼窥,就讓它返回 true 即可
    // 順便戏蔑,`mutation` 是個(gè) { type, payload } 對(duì)象
    return mutation.type !== "aBlacklistedMutation"
  },
  transformer (state) {
    // 在開(kāi)始記錄之前轉(zhuǎn)換狀態(tài)
    // 例如,只返回指定的子樹
    return state.subTree
  },
  mutationTransformer (mutation) {
    // mutation 按照 { type, payload } 格式記錄
    // 我們可以按任意方式格式化
    return mutation.type
  },
  logger: console, // 自定義 console 實(shí)現(xiàn)鲁纠,默認(rèn)為 `console`
})

9总棵、嚴(yán)格模式

const store = new Vuex.Store({
  // ...
// 不要在發(fā)布環(huán)境中開(kāi)啟嚴(yán)格模式航瞭,在嚴(yán)格模式下龄广,無(wú)論何時(shí)發(fā)生了狀態(tài)變更且不是由 mutation 函數(shù)引起的秘案,將會(huì)拋出錯(cuò)誤硕淑。有可能造成性能損失
  strict: process.env.NODE_ENV !== 'production'
})

10休偶、表單處理
對(duì)于希望對(duì)vuex中store里數(shù)據(jù)進(jìn)行雙向綁定時(shí)
10.1座硕、vuex的思路

<input :value="message" @input="updateMessage">
//...
computed: {
  ...mapState({
    message: state => state.obj.message
  })
},
methods: {
  updateMessage (e) {
    this.$store.commit('updateMessage', e.target.value)
  }
}
//...
mutations: {
  updateMessage (state, message) {
    state.obj.message = message
  }
}

10.2莱没、使用帶有 setter 的雙向綁定計(jì)算屬性

<input v-model="message">
//...
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}

11胁编、測(cè)試
檢測(cè)state值是否達(dá)到預(yù)期鹃觉,那么我們主要是針對(duì) Vuex 中的 mutation 和 action 進(jìn)行單元測(cè)試专酗,
11.1、motation
比較好測(cè)盗扇,就是一群一欄參數(shù)的函數(shù) 祷肯,調(diào)用看看是不是符合預(yù)期就好
11.2、action
這個(gè)鏈接很棒:https://zhuanlan.zhihu.com/p/75513490
Action 應(yīng)對(duì)起來(lái)略微棘手疗隶,因?yàn)樗鼈兛赡苄枰{(diào)用外部的 API躬柬。當(dāng)測(cè)試 action 的時(shí)候,我們需要增加一個(gè) mocking 服務(wù)層——例如抽减,我們可以把 API 調(diào)用抽象成服務(wù)允青,然后在測(cè)試文件中用 mock 服務(wù)回應(yīng) API 調(diào)用。為了便于解決 mock 依賴卵沉,可以用 webpack 和 inject-loader 打包測(cè)試文件颠锉。

image.png

image.png

12、熱加載
對(duì)于 mutation 和模塊史汗,你需要使用 store.hotUpdate() 方法

image.png

image.png

https://juejin.im/post/5dba91e4518825647e4ef18b

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琼掠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子停撞,更是在濱河造成了極大的恐慌瓷蛙,老刑警劉巖悼瓮,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異艰猬,居然都是意外死亡横堡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門冠桃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)命贴,“玉大人,你說(shuō)我怎么就攤上這事食听⌒刂耄” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵樱报,是天一觀的道長(zhǎng)葬项。 經(jīng)常有香客問(wèn)我,道長(zhǎng)迹蛤,這世上最難降的妖魔是什么玷室? 我笑而不...
    開(kāi)封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮笤受,結(jié)果婚禮上穷缤,老公的妹妹穿的比我還像新娘。我一直安慰自己箩兽,他們只是感情好津肛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著汗贫,像睡著了一般身坐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上落包,一...
    開(kāi)封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天部蛇,我揣著相機(jī)與錄音,去河邊找鬼咐蝇。 笑死涯鲁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的有序。 我是一名探鬼主播抹腿,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼旭寿!你這毒婦竟也來(lái)了警绩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盅称,失蹤者是張志新(化名)和其女友劉穎肩祥,沒(méi)想到半個(gè)月后后室,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡混狠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年岸霹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片檀蹋。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖云芦,靈堂內(nèi)的尸體忽然破棺而出俯逾,到底是詐尸還是另有隱情,我是刑警寧澤舅逸,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布桌肴,位于F島的核電站,受9級(jí)特大地震影響琉历,放射性物質(zhì)發(fā)生泄漏坠七。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一旗笔、第九天 我趴在偏房一處隱蔽的房頂上張望彪置。 院中可真熱鬧,春花似錦蝇恶、人聲如沸拳魁。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)潘懊。三九已至,卻和暖如春贿衍,著一層夾襖步出監(jiān)牢的瞬間授舟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工贸辈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留释树,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓擎淤,卻偏偏與公主長(zhǎng)得像躏哩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揉燃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • vuex官方文檔 一姑曙、vuex是什么 官方解釋是:Vuex是通過(guò)全局注入store對(duì)象襟交,來(lái)實(shí)現(xiàn)組件間的狀態(tài)共享,是...
    好一只帥鹵蛋閱讀 318評(píng)論 0 1
  • 目錄 1 引入 vuex 2 state 訪問(wèn)狀態(tài)對(duì)象 3 mutations(同步) 模板獲取方法 4 gett...
    林ze宏閱讀 368評(píng)論 0 0
  • Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式伤靠。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)捣域,并以相應(yīng)...
    白水螺絲閱讀 4,667評(píng)論 7 61
  • State 單一狀態(tài)樹 Vuex使用單一狀態(tài)樹——用一個(gè)對(duì)象就包含了全部的應(yīng)用層級(jí)狀態(tài)。至此它便作為一個(gè)“唯一數(shù)據(jù)...
    oWSQo閱讀 1,091評(píng)論 0 0
  • 由于Vuex的官方文檔在各個(gè)模塊之間缺乏一些過(guò)渡宴合,另外新概念很多焕梅,使得初讀時(shí)總有些云里霧里的感覺(jué)。于是本文在官方文...
    一郭鮮閱讀 355評(píng)論 0 1