Vuex學習入門

藝術之因此存在,
    就是爲了令人恢復對生活的感受,
    爲了令人感覺事物,
    使石頭顯出石頭的質感。

                --什克洛夫斯基
複製代碼

什麼是Vuex

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。javascript

Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。html

什麼狀況下須要用Vuex

Vuex 能夠幫助咱們管理共享狀態,並附帶了更多的概念和框架。這須要對短時間和長期效益進行權衡。vue

若是您不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 store 模式就足夠您所需了。可是,若是您須要構建一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。java

總結如下,主要是如下兩點:git

  1. 方便全部組件共享信息,方便不一樣組件共享信息。
  2. 某個組件須要修改狀態和需求。

組件之間傳值方式

主流的幾種Vue的組件間傳遞信息的方式,無非有如下幾種:ajax

  1. 經過$emitprops在父子組件中進行數據傳遞vuex

  2. eventbus(全局事件)在中進行傳遞vue-cli

  3. 利用localstorage、sessionstorage等存儲手段來進行傳遞緩存

毫無疑問,這些個方式都能完成咱們所要的需求,可是在某種程度上面或多或少都有一些問題。例如:安全

  1. 利用$emitprops在兄弟關係嵌套比較深的狀況之下,代碼書寫量將會大大的增長

  2. 全局事件在使用的時候可能被被屢次觸發、銷燬時機掌握等等一系列的問題,同時做爲全局事件全部頁面都能監聽、掌控事件可能會存在安全性問題等等...

  3. ...

針對以上三種傳值方式存在各自的缺點,下面着重介紹如下主角Vuex的簡單入門。

Vuex核心概念

每個 Vuex 應用的核心就是 store(倉庫)。「store」基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有如下兩點不一樣:

  • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得高效更新。

  • 你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。

上面就將vuex的四個核心選項:state mutations getters actions說了出來,下面咱們經過實例來了解這幾個概念。

簡單入門

  • 第一步

新建一個.js 文件,名字位置任意,按照慣例,建議在/src/store,咱們就在該文件裏編輯代碼。

文件位置 /src/store/index.js

// 引入vue 和 vuex
import Vue from 'vue'
import Vuex from 'vuex'

// 這裏須要use一下,固定寫法,記住便可
Vue.use(Vuex)

// 直接導出 一個 Store 的實例
export default new Vuex.Store({
 // 相似 vue 的 data
  state: {
    name: 'oldName'
  },
 // 相似 vue 裏的 mothods(同步方法)
  mutations: {
    updateName (state) {
      state.name = 'newName'
    }
  }
})
複製代碼

這一步其實就是新建一個store,可是咱們還沒在項目中使用。

  • 第二步

在入口文件引入上述文件, 並稍微改一下傳給 new Vue()的參數,新增的行後面有備註。

文件位置 /src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'  //新增

Vue.config.productionTip = false

new Vue({
  router,
  store,  //新增
  render: h => h(App)
}).$mount('#app')

複製代碼

以上2步,若是咱們使用vue-cli腳手架建立初始化項目的時候,選擇了Vuex,以上兩步都是默認幫咱們處理好了的,使用起來很方便。

  • 第三步

以上2步,其實已經完成了vuex的基本配置,接下來就是使用了。

文件位置 /src/App.vue

<template>
  <div>
    {{getName}}
    <button @click="changeName" value="改名">改名</button>
  </div>
</template>

<script> export default { computed:{ getName(){ return this.$store.state.name } }, methods:{ changeName () { this.$store.commit('updateName') } } } </script>
複製代碼

這裏就是一個很普通的vue文件了,有區別的地方是這裏咱們須要用computed屬性去獲取 store 裏的 "data"。

還有就是咱們要改變數據的話,再也不用 this.xxx = xxx 改爲 this.$store.commit('updateName')

四大核心

State

首先是state,如何來獲取state的值呢?通常是將這個值放置在computed裏面,這樣的話一旦數據發生改變的時候,就反饋到頁面上面去。

computed:{
    getName(){
        return this.$store.state.name
    }
 },
複製代碼

state總結:用來存放組件之間共享的數據,它跟組件的data選項相似,只不過data選項是用來存放組件的私有數據。

Getter

如今假設邏輯有變,咱們最終指望獲得的數據(computed中的getName),是基於 this.$store.state.name 上通過複雜計算得來的,恰好這個getName要在好多個地方使用,那麼咱們就得複製好幾份。

vuex 給咱們提供了 getter來解決這個問題,能夠認爲是 store 的計算屬性,請看代碼:

文件位置 /src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
 // 相似 vue 的 data
 state: {
  name: 'oldName'
 },
 // 相似 vue 的 computed -----------------如下5行爲新增
 getters:{
  getReverseName: state => {
    return state.name.split('').reverse().join('')
  }
 },
 // 相似 vue 裏的 mothods(同步方法)
 mutations: {
  updateName (state) {
   state.name = 'newName'
  }
 }
})
複製代碼

而後咱們能夠這樣使用:

文件位置 /src/App.vue

computed:{
  getName(){
   return this.$store.getters.getReverseName
  }
}
複製代碼

事實上, getter 不止單單起到封裝的做用,它還跟vue的computed屬性同樣,會緩存結果數據,只有當依賴改變的時候,纔要從新計算。

getter總結:getters主要是用來過濾和重組,這些事件最好也是能在計算屬性中完成,用於監聽事件變化的。

Mutation

Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的事件類型 (type) 和 一個 回調函數 (handler),且必須是同步方法。

mutation定義:

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
複製代碼

mutation使用:

this.$store.commit('increment', {
  amount: 10
})
複製代碼

mutations總結:

  • 在 Vuex store 中,實際改變 狀態(state) 的惟一方式是經過 提交(commit) 一個 mutation
  • mutations下的函數接收state做爲參數,另外一個參數叫作payload(載荷),payload是用來記錄開發者使用該函數的一些信息,好比說提交了什麼,提交的東西是用來幹什麼的,包含多個字段,因此載荷通常是對象(其實這個東西跟git的commit很相似)
  • 還有一點須要注意,mutations方法必須是同步方法!

Action

細心的你,必定發現我以前代碼裏 mutations 頭上的註釋了 相似 vue 裏的 mothods(同步方法)。

爲何要在 methods 後面備註是同步方法呢? 由於mutation只能是同步的函數,只能是同步的函數,只能是同步的函數!!!

那麼若是咱們想觸發一個異步的操做呢?答案是: action + $dispatch, 咱們繼續修改store/index.js下面的代碼。

文件位置 /src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
 // 相似 vue 的 data
 state: {
  name: 'oldName'
 },
 // 相似 vue 的 computed
 getters:{
  getReverseName: state => {
    return state.name.split('').reverse().join('')
  }
 },
 // 相似 vue 裏的 mothods(同步方法)
 mutations: {
  updateName (state) {
   state.name = 'newName'
  }
 },
 // 相似 vue 裏的 mothods(異步方法) -------- 如下7行爲新增
 actions: {
  updateNameAsync ({ commit }) {
   setTimeout(() => {
    commit('updateName')
   }, 1000)
  }
 }
})
複製代碼

而後咱們能夠再咱們的vue頁面裏面這樣使用:

文件位置 /src/App.vue

methods: {
  rename () {
    this.$store.dispatch('updateNameAsync')
  }
}
複製代碼

actions總結:

  • actions的做用其實和mutations是沒有差異的,無非就是一個同步、異步的差異罷了。而在功能上面主要有一下兩個區別:

    • actions 提交的是mutations,而不是直接變動狀態。也就是說,actions會經過mutations,讓mutations幫他提交數據的變動

    • actions 能夠包含任意異步操做。ajax、setTimeout、setInterval不在話下

    • actions第一個參數是一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters,可是 context 對象不是 store 實例自己。下圖是我從控制檯打印出來的context對象

總結

解釋一下這個圖:

  • vuex 的區域是綠色虛線框的位置

  • 流程:

    • 每次 vue 組件須要 給 vuex 分派 一個 actions,actions 提交一個 mutation,由 mutation 來修改 state,而後再返回給 vue 組件渲染

    • state 狀態只能由 mutation 來修改

    • actions 會能夠封裝各類 mutation 來進行修改 state

  • 關於 state:state 就是狀態

  • 關於 mutation:mutation 是 vuex 對 state 或者 store提交修改的惟一方式,固定方式

  • 關於 getter:

    • 這裏沒有出現 getter, 由於 getter 在這個流程裏面不須要出現,他只是一個屬性,方便從 vuex 的內存裏面獲取一些信息,可看作state的計算屬性
  • 關於 actions:

    • action 提交的是 mutation,而不是直接變動狀態

    • action 能夠包含任意異步操做

下圖是我總結的Vuex功能點思惟導圖:

參考文獻:

Vuex官網

談一談我是怎麼學習使用vuex的

簡單的三步vuex入門

相關文章
相關標籤/搜索