Vue.js學(xué)習(xí)系列二 —— vuex學(xué)習(xí)實踐筆記(附DEMO)

上次學(xué)習(xí)了vue-router的使用,讓我能夠在各個頁面間切換,將頁面搭建了起來。這次則要學(xué)習(xí)vue的狀態(tài)管理模式——vuex。

:本文只是個人對vuex學(xué)習(xí)的一些理解,要深刻掌握還需要認(rèn)真查閱官方文檔。

一、基本介紹

Vuex 是一個專為 Vue.js 的SPA單頁組件化應(yīng)用程序開發(fā)的狀態(tài)管理模式插件。
由于Vue SPA應(yīng)用的模塊化,每個組件都有它各自的數(shù)據(jù)(state)、界面(view)、和方法(actions)。這些數(shù)據(jù)、界面和方法分布在各個組件中,當(dāng)項目內(nèi)容變得越來越多時,每個組件中的狀態(tài)會變得很難管理。這是vuex就派上用場啦~下面我們看一個簡單的vuex例子。

1. 單個組件中的狀態(tài)

假如只是在單個組件中要改變界面view很簡單,只需要改變state數(shù)據(jù)源即可。如下代碼:

<template>
    <div>
      view: {{ count }}
      <button @click="increment">increment</button>
    </div>
</template>

<script>
export default {
  // state
  data () {
    return {
      count: 0
    }
  },
  // actions
  methods: {
    increment () {
      this.count++
    }
  }
}
</script>

所以,單個組件中的原理圖是這樣的:

單個組件中的原理圖

2. 多個組件中的狀態(tài)

然而,我們作為組件化的SPA應(yīng)用,必定會牽扯到多個組件間的通信。
比如有兩個相同的組件A和B,它們共享一個數(shù)據(jù)count,并且都有一個方法可以操作這個count,我們使用vuex來寫。
A組件和B組件的代碼(代碼相同)

<template>
  <div>
    {{ $store.state.count }}
    <button @click="increment">increment</button>
  </div>
</template>

<script>
  export default {
    methods: {
      increment () {
        this.$store.commit('increment')
      }
    }
  }
</script>
結(jié)果1
結(jié)果2

可以看到,這里的兩個increment按鈕點擊都會同時改變兩個count的數(shù)據(jù),因為數(shù)據(jù)源count和方法increment都是全局的。
正如下面官方原理圖所畫的,我們把全局?jǐn)?shù)據(jù)源state、改變數(shù)據(jù)源的方法mutations、異步操作方法actions都放提取出來放到store中,實現(xiàn)全局?jǐn)?shù)據(jù)狀態(tài)單獨管理的功能。

vuex官方原理圖

二、安裝&配置

1. 安裝vuex

使用npm安裝并保存到package.json中:

npm install vuex --save

package.json

  "devDependencies": {
    ...
    "vuex": "^2.1.1",
    ...
  },

2. 配置

配置方式和路由的配置方式差不多

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

Vue.use(Vuex)
//創(chuàng)建Store實例
const store = new Vuex.Store({
  // 存儲狀態(tài)值
  state: {
    ...
  },
  // 狀態(tài)值的改變方法,操作狀態(tài)值
  // 提交mutations是更改Vuex狀態(tài)的唯一方法
  mutations: {
    ...
  },
  // 在store中定義getters(可以認(rèn)為是store的計算屬性)。Getters接收state作為其第一個函數(shù)
  getters: {
    ...
  },
  actions: { 
    ...
  }
})
// 要改變狀態(tài)值只能通過提交mutations來完成

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
  // 將store實例注入到根組件下的所有子組件中
  store
  // 子組件通過this.$store來方位store
})

三、核心概念

1. state

state就是全局的狀態(tài)(數(shù)據(jù)源),我們可以用以下方式在Vue 組件中獲得Vuex的state狀態(tài)
template

  <div>
    {{ $store.state.count }}
  </div>

script

console.log(this.$store.state.count)

2. getters

getters其實可以認(rèn)為是 store 的計算屬性,用法和計算屬性差不多。
定義getter:

  getters: {
    done(state) {
      return state.count + 5;
    },
  }

使用getter

console.log(this.$store.getters.done)

3. mutations

mutations是操作state的唯一方法,即只有mutations方法能夠改變state狀態(tài)值。

3.1 基本操作

mutations對state的操作

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

組件通過commit提交mutations的方式來請求改變state

this.$store.commit('increment')

這樣的好處是我們可以跟蹤到每一次state的變化,以便及時分析和解決問題。

3.2 提交載荷(Payload)

mutations方法中是可以傳參的,具體用法如下:

  mutations: {
    // 提交載荷 Payload
    add(state, n) {
      state.count += n
    }
  },
this.$store.commit('add', 10)

這里只是傳了一個數(shù)字,在大多數(shù)情況下,載荷應(yīng)該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀。

3.3 注意

mutations方法必須是同步方法!

4. actions

4.1 基本操作

之前說mutations方法必須只能是同步方法,為了處理異步方法,actions出現(xiàn)了。關(guān)于action和mutations的區(qū)別有以下幾點:

  • Action 提交的是 mutation,而不是直接變更狀態(tài)。
  • Action 可以包含任意異步操作。
  • Action 還是得通過 mutation 方法來修改state
    同樣是之前的increment方法,我們分別用同步和異步的action來驗證上面所說的與mutations的不同之處:
  actions: {
    increment (context) {
      context.commit('increment')
    },
    incrementAsync (context) {
      // 延時1秒  
      setTimeout(() => {
        context.commit('increment')
      }, 1000)
    }
  },

不同于mutations使用commit方法,actions使用dispatch方法。

this.$store.dispatch('incrementAsync')

4.2 context

context是與 store 實例具有相同方法和屬性的對象。可以通過context.statecontext.getters來獲取 state 和 getters。

4.3 以載荷形式分發(fā)

    incrementAsyncWithValue (context, value) {
      setTimeout(() => {
        context.commit('add', value)
      }, 1000)
    }
this.$store.dispatch('incrementAsyncWithValue', 5)

5. module

使用單一狀態(tài)樹,導(dǎo)致應(yīng)用的所有狀態(tài)集中到一個很大的對象。但是,當(dāng)應(yīng)用變得很大時,store 對象會變得臃腫不堪。
為了解決以上問題,Vuex 允許我們將 store 分割到模塊(module)。每個模塊擁有自己的 state、mutation、action、getters、甚至是嵌套子模塊——從上至下進(jìn)行類似的分割:

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)

module其實還是對于大型的SPA應(yīng)用來說的,暫時對module的應(yīng)用和理解并沒有太多,之后會補(bǔ)上這一塊兒的內(nèi)容。
想要了解更多module知識,請查閱官方module文檔

Vue.js學(xué)習(xí)系列

鑒于前端知識碎片化嚴(yán)重,我希望能夠系統(tǒng)化的整理出一套關(guān)于Vue的學(xué)習(xí)系列博客。

Vue.js學(xué)習(xí)系列一 —— vue-router2學(xué)習(xí)實踐筆記(附DEMO)
Vue.js學(xué)習(xí)系列二 —— vuex學(xué)習(xí)實踐筆記(附DEMO)
Vue.js學(xué)習(xí)系列三 —— axios和網(wǎng)絡(luò)傳輸相關(guān)知識的學(xué)習(xí)實踐
Vue.js學(xué)習(xí)系列四 —— Webpack打包工具的使用
Vue.js學(xué)習(xí)系列五 —— 從VUE-CLI來聊聊ESLint
Vue.js學(xué)習(xí)系列六 —— Vue單元測試Karma+Mocha學(xué)習(xí)筆記
Vue.js學(xué)習(xí)系列七 —— Vue服務(wù)器渲染Nuxt學(xué)習(xí)
Vue.js學(xué)習(xí)系列八 —— Vue源碼學(xué)習(xí)之State學(xué)習(xí)

Vue.js學(xué)習(xí)系列項目地址

本文源碼已收入到GitHub中,以供參考,當(dāng)然能留下一個star更好啦-。
https://github.com/violetjack/VueStudyDemos

關(guān)于作者

VioletJack,高效學(xué)習(xí)前端工程師,喜歡研究提高效率的方法,也專注于Vue前端相關(guān)知識的學(xué)習(xí)、整理。
歡迎關(guān)注、點贊、評論留言~我將持續(xù)產(chǎn)出Vue相關(guān)優(yōu)質(zhì)內(nèi)容。

新浪微博: http://weibo.com/u/2640909603
掘金:https://gold.xitu.io/user/571d953d39b0570068145cd1
CSDN: http://blog.csdn.net/violetjack0808
簡書: http://www.itdecent.cn/users/54ae4af3a98d/latest_articles
Github: https://github.com/violetjack

打個廣告

鏈家上海研發(fā)中心招聘前端、后端、測試。
機(jī)會不多,需要內(nèi)推機(jī)會的請將簡歷發(fā)送至 dingxiaojie001@ke.com。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容