vuex的使用

1.簡介

1.1Vuex是什么

Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。

Vuex其實是管理數(shù)據(jù)狀態(tài)的一個庫。通過創(chuàng)建一個集中的數(shù)據(jù)存儲供程序中所有組件訪問,

簡單來說,用來集中管理數(shù)據(jù),類似于React中的Redux,都是基于Flux的前端狀態(tài)管理框架

image.png

在應(yīng)用 vuex 之前,我們還是需要看懂這個流程圖。

① Vue Components 是我們的 vue 組件,組件會觸發(fā)(dispatch)一些事件或動作,也就是圖中的 Actions;
② 我們在組件中發(fā)出的動作,肯定是想獲取或者改變數(shù)據(jù)的,但是在 vuex 中,數(shù)據(jù)是集中管理的,我們不能直接去更改數(shù)據(jù),所以會把這個動作提交(Commit)到 Mutations 中;
③ 然后 Mutations 就去改變(Mutate)State 中的數(shù)據(jù);
④ 當 State 中的數(shù)據(jù)被改變之后,就會重新渲染(Render)到 Vue Components 中去,組件展示更新后的數(shù)據(jù),完成一個流程。

官網(wǎng)地址:https://vuex.vuejs.org/zh/

1.2為什么要使用Vuex?

當我們的應(yīng)用遇到多個組件共享狀態(tài)時,單向數(shù)據(jù)流的簡潔性很容易被破壞:

  • 多個視圖依賴于同一狀態(tài)。

  • 來自不同視圖的行為需要變更同一狀態(tài)。

  • 對于問題一,傳參的方式對于多層嵌套的組件將會非常繁瑣,并且對于兄弟組件間的狀態(tài)傳遞無能為力。

  • 對于問題二,我們經(jīng)常會采用父子組件直接引用或者通過事件來變更和同步狀態(tài)的多份拷貝。以上的這些模式非常脆弱,通常會導(dǎo)致無法維護的代碼。

image.png

什么情況下我應(yīng)該使用 Vuex

  • 如果您不打算開發(fā)大型單頁應(yīng)用,使用 Vuex 可能是繁瑣冗余的。
  • 如果應(yīng)用夠簡單,最好不要使用 Vuex。一個簡單的 store 模式就足夠您所需了。但是,如果需要構(gòu)建一個中大型單頁應(yīng)用,很可能會考慮如何更好地在組件外部管理狀態(tài),Vuex 將會成為自然而然的選擇

2. 基本用法

2.1 安裝vuex

cnpm install vuex -S

* vue cli 3 中搭建腳手架預(yù)設(shè)時選擇了“vuex”后便安裝了vuex,可跳過此步閱讀

2.2 創(chuàng)建store.js文件,在main.js中導(dǎo)入并配置store.選項

import store from './store'  //引入文件

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


2.3 編輯store.js文件

Vuex的核心是Store(倉庫),相當于是一個容器,一個store實例中包含以下屬性的方法:
    state       定義屬性(狀態(tài)、數(shù)據(jù))
    getters     用來獲取屬性
    actions     定義方法(動作)、異步操作
    commit      提交變化,修改數(shù)據(jù)的唯一方式就是顯式的提交mutations,并且這個過程是同步的
    mutations   修改狀態(tài)
    
    注:不能直接修改數(shù)據(jù),必須顯式提交變化,目的是為了追蹤到狀態(tài)的變化

store.js 中寫入:

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

Vue.use(Vuex)

//vuex中的數(shù)據(jù)源,我們需要保存的數(shù)據(jù)就保存在這里,可以在頁面通過 this.$store.state來獲取我們定義的數(shù)據(jù);
var state = {
  count: 2
}

//定義getters
// Getter相當于vue中的computed計算屬性,
// getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當它的依賴值發(fā)生了改變才會被重新計算,
// 這里我們可以通過定義vuex的Getter來獲取,Getters 可以用于監(jiān)聽、state中的值的變化,返回計算后的結(jié)果
var getters = {
  getterCount (state) {
    return state.count + 1
  }
}

//如果需要修改store中的值唯一的方法就是提交mutation來修改
const mutations = {
  mutationsAddCount (state) {
    state.count++;
  },
  reduction (state) {
    state.count--;
  }
}

//定義actions
//Action 類似于 mutation,不同在于:
//   Action 提交的是 mutation,而不是直接變更狀態(tài)。
//   Action 可以包含任意異步操作。
const actions = {
  // actionsAddCount (context) {//包含:commit、dispatch、state
  //   console.log(context);
  //   commit 提交變化,修改數(shù)據(jù)的唯一方式就是顯式的提交 mutations
  //   context.commit('mutationsAddCount')
  // },
  actionsAddCount ({ commit, state }) {
    // ({commit,state}) 這種寫法是 es6 中的對象解構(gòu)
    commit('mutationsAddCount'); //提交一個名為mutationsAddCount的變化,名稱可自定義,可以認為是類型名,
    //和 mutations 中的 mutationsAddCount 對應(yīng)
  },
  reduction ({ commit, state }) {
    commit('reduction');
  },
  addAsync ({ commit, state }) {
    //異步操作
    var p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 3000);
    });

    p.then(() => {
      commit('mutationsAddCount');
    }).catch(() => {
      console.log('異步操作');
    });
  }
}

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions
})

2.3.1 State:

vuex中的數(shù)據(jù)源,我們需要保存的數(shù)據(jù)就保存在這里,可以在頁面通過 this.$store.state來獲取我們定義的數(shù)據(jù),我們新建一個Test.vue組件,并在Test.vue中調(diào)用它。

image.png

調(diào)用:

image.png

頁面上:

image.png
2.3.2 Getters:

Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當它的依賴值發(fā)生了改變才會被重新計算。

image.png

調(diào)用:

image.png

頁面上:

image.png
2.3.3 Mutations:

數(shù)據(jù)我們在頁面已經(jīng)獲取到了,但是如果我們需要修改count值怎么辦?如果需要修改store中的值唯一的方法就是提交mutation來修改

添加mutations,在mutations中定義兩個函數(shù),用來對count加1和減1

image.png

Test.vue文件中添加兩個按鈕,一個加1,一個減1;這里我們點擊按鈕調(diào)用addFun(執(zhí)行加的方法)和reductionFun(執(zhí)行減法的方法),然后在里面直接提交mutations中的方法修改值:

image.png

頁面上點擊+、- 按鈕操作數(shù)據(jù):

點擊 “+”按鈕

image.png

再點擊:

image.png
2.3.4 Actions:

mutation中是存放處理數(shù)據(jù)的方法的集合,我們使用的時候需要commit。但是commit是同步函數(shù),而且只能是同步執(zhí)行。那我們想異步操作怎么辦?

這個時候就需要用到actions了

在actions中提交mutation,并且可以包含任何的異步操作行。actions可以理解為通過將mutations里面處里數(shù)據(jù)的方法變成可異步的處理數(shù)據(jù)的方法,簡單的說就是異步操作數(shù)據(jù)(但是還是通過mutation來操作,因為只有它能操作)

image.png
image.png

使用dispath來觸發(fā):

image.png

我們點擊頁面,效果是一樣的。

image.png

這里已經(jīng)實現(xiàn)了一個基本的vuex修改狀態(tài)值的完整流程,如果我們需要指定加減的數(shù)值,那么我們可以在dispatch中傳入第二個參數(shù),然后在actions中的對應(yīng)函數(shù)中接收參數(shù):


image.png
image.png
image.png
2.3.5 mapState、mapGetters、mapActions

我們在子組件中是通過“this.stroe.state.count”、“this.store.dispatch('fnName')”訪問的,看起來并不是那么簡潔 ,vuex官方給了我們一個更簡單的方式來使用vuex, 也就是 {mapState, mapMutations, mapActions, mapGetters}

mapState 用來獲取state
mapGetters 用來獲取屬性(數(shù)據(jù))

mapActions 用來獲取方法(動作)

在Test.vue文件中,調(diào)用代碼如下:

<template>
  <div>
    <!-- 對應(yīng) mapState 中的count -->
    <div>我是直接獲取的值:{{count}}</div>

    <!-- 對應(yīng) mapGetters 中的 getterCount -->
    <div>我是從getters獲取的計算后的值:{{getterCount}}</div>
    <button @click="addFn">點擊+1</button>
    <button @click="reductionFn">點擊-1</button>
  </div>
</template>
<script>
import { mapActions, mapState, mapGetters } from 'vuex'
export default {
  name: "detail",
  data () {
    return {}
  },
  components: {

  },
  computed: {
    //在這里映射 store.state.count,使用方法和 computed 里的其他屬性一樣
    ...mapState(['count']),
    // 使用對象展開運算符將 getter 混入 computed 對象中
    ...mapGetters([
      'getterCount'
    ])
    // ...mapGetters({
    //   myCount: 'getterCount' // getterCount 不是字符串,對應(yīng)的是getter里面的一個方法名字 然后將這個方法名字重新取一個別名 myCount
    // })
  },
  methods: {
    //在這里引入 action 里的方法,使用方法和 methods 里的其他方法一樣
    ...mapActions([
      'actionsAddCount',  //該actionsAddCount來自store.js中導(dǎo)出的 actions 中的 actionsAddCount 
      'reduction'
    ]),

    addFn () {
      this.actionsAddCount()
    },
    reductionFn () {
      this.reduction()
    }
  }
}
</script>

3. Vuex模塊化

當應(yīng)用變得非常復(fù)雜時,store 對象就有可能變得相當臃腫。

為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割

    |-store
        |-index.js
        |-getters.js
        |-actions.js
        |-mutations.js
        |-modules  //模塊文件 分為多個模塊,每個模塊都可以擁有自己的state、getters、actions、mutations
            |-user.js
            |-cart.js
            |-goods.js
            |-order.js
            |....

index.js中引入:

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

//
import user from './module/user'
import card from './module/card'
import goods from './module/goods'
import order from './module/order'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //
  },
  mutations: {
    //
  },
  actions: {
    //
  },
  modules: {
    user,
    card,
    goods,
    order
  }
})

調(diào)用:this.$store.state.user.userId

?著作權(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)容

  • 配置 vuex 和 vuex 本地持久化 目錄 vuex是什么 vuex 的五個核心概念State 定義狀態(tài)(變量...
    稻草人_9ac7閱讀 972評論 0 5
  • vuex的使用 一、配置 1、在store/index中配置 2、導(dǎo)入maiin.js,傳入根組件中 二、stat...
    風(fēng)的記憶乀閱讀 1,500評論 0 0
  • 備注:此案例是用vue腳手架創(chuàng)建的demo 1、首先要知道什么是Vuex? 在Vue官方網(wǎng)站的解釋是:Vuex 是...
    浪流兒閱讀 4,145評論 0 3
  • 安裝 npm npm install vuex --save 在一個模塊化的打包系統(tǒng)中,您必須顯式地通過Vue.u...
    蕭玄辭閱讀 3,040評論 0 7
  • 在 vue 開發(fā)中,組件通信一直是一大痛點。 當項目是很簡單的 SPA 或者多入口項目時,可以靠著 vue 自帶的...
    若年閱讀 1,817評論 0 4

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