Vuex從入門到實(shí)戰(zhàn)(一)

由于多個(gè)狀態(tài)分散的跨越在許多組件和交互間各個(gè)角落震叮,大型應(yīng)用復(fù)雜度也經(jīng)常逐漸增長知举。為了解決這個(gè)問題金顿,Vue 提供 vuex:我們有受到 Elm 啟發(fā)的狀態(tài)管理庫日丹。vuex 甚至集成到 vue-devtools,無需配置即可訪問時(shí)光旅行怎抛。

狀態(tài)管理

狀態(tài)的初始化

狀態(tài)管理仰税,我們應(yīng)該并不陌生。

舉個(gè)例子抽诉,超市里新進(jìn)了一批商品,管理員給這些商品分類吐绵,建立索引迹淌,然后按照順序放入貨架的過程就是最簡單的狀態(tài)管理。

let goods1 = {
  category: 'fruit',
  name: 'apple',
  quantity: 5
}

let goods2 = {
  category: 'supplies',
  name: 'toothbrush',
  quantity: 5
}

let goods3 = {
  category: 'clothes',
  name: 'sweater',
  quantity: 5
}

簡單歸類后 :

let shop = {
  goods: {
    fruit: [{ name: 'apple', quantity: 5 }],
    supplies: [{ name: 'toothbrush', quantity: 5 }],
    clothes: [{ name: 'sweater', quantity: 5 }]
  }
}

這樣己单,當(dāng)我們需要某一商品時(shí)唉窃,很容易根據(jù)類目檢索到這個(gè)商品 :

console.log(shop.goods.fruit.find(f => f.name === 'apple'))
//-> { name: 'apple', quantity: 5 }

狀態(tài)的改變

當(dāng)有顧客前來購買商品時(shí),我們需要類似的操作來減少被購買商品的數(shù)量 :

shop.goods.fruit.find(f => f.name === 'apple').quantity --

然而在成千上萬的交易量背后纹笼,你不知道這些商品被購買的詳細(xì)情況纹份,你甚至不知道上周賣出了多少蘋果,你也就無從得知下周該進(jìn)多少廷痘。

所以你需要一個(gè)賬目來記錄商品購買明細(xì) :

let account = {
  appleSold (value) {
    console.log("apple sold " + value)
    shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
  }
}

當(dāng)賣出蘋果時(shí)蔓涧,POS機(jī)“滴”一聲,記錄生成了 :

account.appleSold (5)
//-> apple sold 5

最簡單的store

于是笋额,我們得到了一個(gè)最簡單的store :

let shop = {
  goods: {
    fruit: [{ name: 'apple', quantity: 5 }],
    supplies: [{ name: 'toothbrush', quantity: 5 }],
    clothes: [{ name: 'sweater', quantity: 5 }]
  },
  account: {
    appleSold (value) {
      console.log("apple sold " + value)
      shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
    },
    funcN () { }
  }
}

由此可知元暴,狀態(tài)管理可以幫助我們更友好的改變狀態(tài),同時(shí)兄猩,跟蹤狀態(tài)變化的軌跡茉盏。

Vue(x) er 須知

開始

Vuex 官方文檔:

https://vuex.vuejs.org/zh-cn/getting-started.html

Vuex最核心的概念 :

  1. Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候枢冤,若 store 中的狀態(tài)發(fā)生變化鸠姨,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新。
  2. 你不能直接改變 store 中的狀態(tài)淹真。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation讶迁。這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用趟咆。

下面對(duì)此拓展:

對(duì)象引用

下面這兩段代碼將輸出什么? 先不要往下看, 自己寫一下

let store = {
  state: {
    msg: "welcome"
  }
}, copy = store.state;
store.state = {
  hello: "world"
};
console.log(Object.keys(copy));
let store = {
  state: {
    msg: 'welcome'
  }
}, copy = store.state;
store.state.hello = "world";
console.log(Object.keys(copy))

結(jié)果如下(如果你都答對(duì)了添瓷,那么理解和上手Vuex將會(huì)很輕松) :

//-> ["msg"]
//-> ["msg", "hello"]

提交和分發(fā)

vuex 只是一個(gè)工具梅屉,或許過了這段時(shí)間,過了這個(gè)項(xiàng)目鳞贷,你就不會(huì)再用它坯汤。

我們要記住的是它留給我們的啟示:

不要直接更改狀態(tài), 而是通過提交(commit)和分發(fā)(dispatch)的方法通知管理者改變對(duì)象狀態(tài),這是大型項(xiàng)目和復(fù)雜狀態(tài)管理的最佳實(shí)踐搀愧。

Vuex 核心概念

一個(gè)完整的 Vuex Store

/**
 * index.js
 */
import axios from 'axios'

const store = new Vuex.Store({
  state: {
    counter: 0
  },
  getters: {
    counter: state => state.counter
  },
  // 可處理異步請(qǐng)求惰聂, dispatch 觸發(fā)
  actions: {
    askPermission ({commit}) {
      axios.get('/url').then((res) => {
        if(res.data.permission)
          commit('addCounter')
      }).catch((err) => {
        console.log('Error: in process "Ask permission".\n Detailed: ' + err)
      })
    }
  },
  // 同步, commit 觸發(fā)
  mutations: {
    addCounter (state) {
      state.counter ++
    }
  }
})

PS: 仔細(xì)研究一下 dispatch & actions, commit & mutations, 是否有一種似曾相識(shí)的感覺?

Look, 看這對(duì) emit & on (事件機(jī)制),同樣的事件類型咱筛,同樣的回調(diào)函數(shù)搓幌。

State

單一狀態(tài)樹

Vuex使用單一狀態(tài)樹,一個(gè)state對(duì)象包含全部應(yīng)用層狀態(tài)迅箩,使得一個(gè)應(yīng)用只有唯一數(shù)據(jù)源(SSOT, Single Source of Truth)

這對(duì)模塊化并不造成影響

state: {
  moduleA: {

  },
  moduleB: {

  }
}

Getter

state: {
  prop: ''
}

你可以使用store.state.prop直接讀取狀態(tài)的值, 當(dāng)然也可以使用Getter :

getters: {
  prop = state => state.prop
}

使用Getter的好處在于溉愁,你可以從state中派生出一些狀態(tài) :

getters: {
  prop = state => state.prop,
  fixedProp = state => state.prop || '暫無'
}

Mutation

Vuex 中的 mutation 類似于事件,有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)饲趋,回調(diào)函數(shù)的接受state作為第一個(gè)參數(shù)拐揭,我們?cè)谶@里修改狀態(tài)(state)

state: {
  counter: 0
},
mutations: {
  addCounter (state) {
    state.counter ++
  },
  addCounter (state, payload) {
    state.counter += payload.value
  }
}

通過 commit 通知狀態(tài)變化

store.commit('addCounter')
store.commit('addCounter', {value: 1})

Action

類似于mutation,不同在于

  • 只能通過 commit mutation 通知狀態(tài)變化
  • mutation 只能包含同步操作,而 action 可以包含異步操作(比如, 在這里可以執(zhí)行ajax請(qǐng)求)
actions: {
  askPermission ({commit}) {
    axios.get('/url').then((res) => {
      if(res.data.permission)
        commit('addCounter')
    }).catch((err) => {
      console.log('Error: in process "Ask permission".\n Detailed: ' + err)
    })
  },
  askPermission ({commit}, payload) {
    axios.get('/url', { params:payload }).then((res) => {
      if(res.data.permission)
        commit('addCounter')
    }).catch((err) => {
      console.log('Error: in process "Ask permission".\n Detailed: ' + err)
    })
  }
}

通過 dispatch 通知狀態(tài)變化

store.dispatch('askPermission')
store.dispatch('askPermission', { author: "lonelydawn" })

Module

Vuex 允許我們將store分割成模塊奕塑,每個(gè)模塊擁有自己的state, mutation, action, getter, 甚至是嵌套子模塊 :

const store = new Vuex.Store({
  modules: {
    a: {
      state: {},
      mutations: {
        addCounter(state) {}
      },
      actions: {},
      getters: {}
    },
    b: {
      namespaced: true, // 建立命名空間
      state: {},
      mutations: {
        addCounter(state) {}
      },
      actions: {}
    }
  }
})

store.state.a
store.state.b

//  提交 給 模塊 a 的 mutations
store.commit('addCounter')
//  提交 給 模塊 b 的 mutations
store.commit('b/addCounter')

最后

Vuex 的基本用法已經(jīng)介紹完了堂污。

相關(guān)內(nèi)容 :

官方文檔: https://vuex.vuejs.org/zh-cn/

官方實(shí)例: https://github.com/vuejs/vuex/tree/dev/examples

在下列內(nèi)容中, 我將 演示如何使用 vue + vuex 以及其他常用組件從入門到實(shí)戰(zhàn)龄砰。

Vuex從入門到實(shí)戰(zhàn)(二)

Vuex從入門到實(shí)戰(zhàn)(三)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盟猖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子换棚,更是在濱河造成了極大的恐慌式镐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件固蚤,死亡現(xiàn)場(chǎng)離奇詭異碟案,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)颇蜡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門价说,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人风秤,你說我怎么就攤上這事鳖目。” “怎么了缤弦?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵领迈,是天一觀的道長。 經(jīng)常有香客問我,道長狸捅,這世上最難降的妖魔是什么衷蜓? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮尘喝,結(jié)果婚禮上磁浇,老公的妹妹穿的比我還像新娘。我一直安慰自己朽褪,他們只是感情好置吓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缔赠,像睡著了一般衍锚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗤堰,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天戴质,我揣著相機(jī)與錄音,去河邊找鬼踢匣。 笑死置森,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的符糊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呛凶,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼男娄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漾稀,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤模闲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后崭捍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尸折,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年殷蛇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了实夹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粒梦,死狀恐怖亮航,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匀们,我是刑警寧澤缴淋,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響重抖,放射性物質(zhì)發(fā)生泄漏露氮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一钟沛、第九天 我趴在偏房一處隱蔽的房頂上張望畔规。 院中可真熱鬧,春花似錦讹剔、人聲如沸油讯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽陌兑。三九已至,卻和暖如春由捎,著一層夾襖步出監(jiān)牢的瞬間兔综,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工狞玛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留软驰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓心肪,卻偏偏與公主長得像锭亏,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子硬鞍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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

  • vuex是一個(gè)狀態(tài)管理模式慧瘤,通過用戶的actions觸發(fā)事件,然后通過mutations去更改數(shù)據(jù)(你也可以說狀態(tài)...
    Ming_Hu閱讀 2,023評(píng)論 3 3
  • 安裝 npm npm install vuex --save 在一個(gè)模塊化的打包系統(tǒng)中固该,您必須顯式地通過Vue.u...
    蕭玄辭閱讀 2,937評(píng)論 0 7
  • Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式锅减。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)...
    白水螺絲閱讀 4,667評(píng)論 7 61
  • Vuex是什么伐坏? Vuex 是一個(gè)專為 Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式怔匣。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件...
    蕭玄辭閱讀 3,117評(píng)論 0 6
  • Vuex 是什么? ** 官方解釋:Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式**桦沉。它采用集中...
    Rz______閱讀 2,306評(píng)論 1 10