Vuex入門簡單易懂系列(一)

在 學習vue 開發中,組件通訊一直是一大痛點。
當項目是很簡單的 SPA 或者多入口項目時,能夠靠着 vue 自帶的 prop/$emit 進行組件通訊;規模再大一些,能夠搭配使用 bus 總線進行兄弟組件通訊;項目再大一些,出現更復雜的組件關係時,複雜的組件通訊可讓你寫得懷疑人生。
萬幸的是, vue 官方出品了 vuex ,經過全局式的狀態管理,解決了這一痛點。
雖然 vuex 很好用,可是,不少小夥伴和我吐槽 vuex 的文檔和 vue-ssr 的文檔同樣,讓人看得一臉懵逼。vue

安裝並引入

正常狀況下,咱們使用 vue-cli3 生成項目時,能夠選擇集成 vuex 到項目中。此時, vue-cli3 會自動安裝 vuex ,並在 src 文件夾下生成 store.js 完成 vuex 的引入和配置。
可是,不少同窗並無使用 vue-cli3 或者生成項目時沒有選擇集成 vuex 。此時,就只能手動安裝並引入 vuex 了。vuex

安裝

因爲 vuex 是用於全局狀態管理的,因此,它不只僅做用於開發環境,並且還要用於生產環境。
顯而易見,安裝 vuex 應該使用 -S 即 --save 命令。
npm install vuex -Svue-cli

引入

相似於 vue-cli3 生成的項目,咱們在 src 文件夾下新建 store.js ,並在其中寫入:npm

// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({})

而後,咱們只須要在 vue 實例中引入 store.js 中的 Vuex.Store 實例便可:app

// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

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

Vuex的使用

完成了 vuex 的安裝和引入,接下來咱們進入 Vuex 的使用。
vuex 中有三要素: state, mutation 以及 action 。它們之間的關係能夠用官網那張著名的圖來表示:異步

clipboard.png

重點來了 (State)

簡單來講, state 表示狀態,相似於 vue 中的 data (其實本質上就是差很少的, vuex 在 vue 的 beforeCreate 鉤子中將 state 混入進 data)。可是,它們又有很大的不一樣: 在使用者看來, state 是全局的,這得益於 vuex 的設計理念——單一狀態樹。這些我將在後幾篇文章中詳細,如今咱們只須要知道 state 是相似於全局下的 data 。
接下來咱們經過一個簡單例子來感覺下 state :
首先,咱們須要修改 store.js 文件,配置 state 。能夠看到,咱們在生成 Vuex.Store 實例時傳入了實例化選項對象,對象包含一個 state 屬性, state 對象的屬性就是咱們定義的全局狀態。
此時,咱們定義了一個全局狀態——count ,並將其的初始值設爲1。工具

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // 添加state
  state: {
    count: 1
  }
})

接下來,咱們須要在組件中引用 count,因爲它是全局狀態,咱們能夠在任何一個組件中使用。爲了展現其威力,咱們在兩個不一樣的組件中使用它。
首先咱們在 App.vue 中使用它:
在模板中,咱們使用 $store.state.count 引入該全局狀態,沒錯,使用它就是那麼簡單,只須要 以 $store.state.key 的形式調用。學習

// App.vue
<template>
  <div id="app">
    <div id="nav">
      {{$store.state.count}}
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

能夠發現, Home 前多出了一個 1 ,這表明着咱們成功引入了全局狀態 count 。
接下來咱們在 Home.vue 的子組件 HelloWorld.vue 中引入 count 。
相同的引用方式: $store.state.count優化

// HelloWorld.vue
<template>
  <div class="hello">
    {{$store.state.count}}
  </div>
</template>

能夠發現,success。網站

Mutation

可是,上面的示例有個問題,那就是全局狀態是靜態的。若是在實際應用場景中,通常來講,會常常更改狀態。
有的同窗會說,咱們直接在方法中修改 this.$store.state.key 的值不就好了嗎?
很差意思,固然是不行的。
state 和 data 的另外一大區別在於,你不能直接改變 state 。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。
簡而言之,咱們把 mutation 當作接收 state 做爲參數並修改 state 的自定義事件便可,上一段所說的 commit 就是觸發 mutaion 這個自定義事件的方法。
光說不練假把式,接下來,咱們對爲 vuex 添加上 mutation ,實現 state 的動態改變:
首先,固然是修改生成 Vuex.Store 示例的選項對象,爲其添加 mutations 。

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  // 添加mutation
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

在上面的代碼中,咱們添加了一個名爲 increment 的 mutation 。完成了自定義事件,接下來,咱們只須要在組件中對 mutation 進行觸發便可。
咱們在 HelloWorld.vue 添加一個按鈕,每次點擊觸發一次 increment 這個 mutation 。能夠發現,觸發方式很簡單,只須要調用 store 自帶的 commit 方法,其中參數爲須要觸發的 mutation 的名稱。

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.commit('increment')">修改count</button>
  </div>
</template>

點擊頁面中的按鈕,你會發現,頁面中的兩個 count 都同時增長了1,說明咱們成功實現了 state 的動態修改。

Action

action 相似於 mutation ,也至關於一種自定義事件。只不過, action 操做的是 mutation 而不是 state 。
添加 action 的方法相似,在選項對象中新增 action 屬性便可。與 mutation 的參數不一樣, action 的參數就是當前建立的 Vue.store 對象實例的上下文,通常將其命名爲 context 。咱們須要使用其自帶的 commit 方法來觸發 mutation 。
下面我經過實際的例子來嘗試下 action :
首先,修改選項對象,使得新添加的 action 能夠觸發以前的 mutation :

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment ({ commit }) {
      commit('increment')
    }
  }
})

因爲咱們通常來講僅僅須要 context 中的 commit 方法,因此能夠採用解構的方式,直接調用 commit 方法,而不須要以 context.commit 的方式使用它。
接下來,只須要修改 HelloWorld.vue ,使其可以在點擊按鈕時觸發便可。
action 的觸發方式和 mutation 相似,只不過調用的方法是 dispatch 。

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.dispatch('increment')">修改count</button>
  </div>
</template>

點擊頁面按鈕,你會發現,實現了和以前相同的效果。

總結

學會了 vuex 三jian客: state , mutation , action ,咱們再回過頭看看前面的那張關係圖,此時應該很容易理解了吧?
組件交互觸發 action , 在 action 中進行異步操做(可選)並觸發 mutation , mutation 控制 state 的變更, state 修改以後,觸發響應式,從新渲染組件。
PS(其餘的進階用法,如: getter , module , 簡寫以及 vuex 項目結構優化,甚至 vuex 源碼解析將會在以後的文章一一講解)

最後

我的認爲對不少新手在入門時(無論學習什麼東西),無可厚非最好剛開始是看視頻。So,一份付出一份收穫。若是你有須要購買學習視頻的能夠訪問該網站加羣http://www.wantmore.top,也能夠直接添加羣號:157285015。偶爾會分享學習乾貨噢!

相關文章
相關標籤/搜索