5分鍾讓你掌握Vuex,深入淺出


5分鍾讓你掌握Vuex,深入淺出

一、什么是Vuex?

概念:Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

簡單點來說(說人話),就是實現任意組件中通信,並可以檢測數據的變化。

二、Vuex原理

Vuex是集中於MVC模式中的Model層,規定所有的數據操作必須通過 action - mutation - state 的流程來進行,再結合Vue的數據視圖v-moder等雙向綁定特性來實現頁面的展示更新。

下面看一張圖來了解全過程。

簡述主要方法詳情:

  • Vue Components:Vue組件。展示頁面,負責接收用戶操作等交互行為,執行dispatch方法觸發對應action進行回應。
  • dispatch:操作行為觸發方法。是唯一能執行action的方法。
  • actions:操作行為處理模塊。處理Vue Components接收到的所有交互行為。包含同步/異步操作,支持多個同名方法,按照注冊的順序依次觸發。向后台API請求的操作就在這個模塊中進行,包括觸發其他action以及提交mutation的操作。該模塊提供了Promise的封裝,以支持action的鏈式觸發。
  • commit:狀態改變提交操作方法。對mutation進行提交,是唯一能執行mutation的方法。
  • mutations:狀態改變操作方法。是Vuex修改state的唯一推薦方法,其他修改方式在嚴格模式下將會報錯。該方法只能進行同步操作,且方法名只能全局唯一。操作之中會有一些hook暴露出來,以進行state的監控等。
  • state:頁面狀態管理容器對象。集中存儲Vue components中data對象的零散數據,全局唯一,以進行統一的狀態管理。頁面顯示所需的數據從該對象中進行讀取,利用Vue的細粒度數據響應機制來進行高效的狀態更新。

總的一句話簡述就是:

Vue組件接收交互行為,調用dispatch方法觸發action相關處理,若頁面狀態需要改變,則調用commit方法提交mutation修改state,通過getters獲取到state新值,響應數據或狀態給Vue 組件,界面隨之更新。

三、Vuex的使用

1.安裝

npm install vuex --save

2.新建一個文件夾store,創建inde.js

隨便叫啥,隨便建不建立文件夾。為了規范。

在這里插入圖片描述

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

//准備actions---用於響應組件中的動作
const actions={
}
//准備mutations---用於操作數據(state)
const mutations={    
}
//准備state---相當於data,用於存儲數據
const state={
    
}
//實例化創建並導出store
export default new Vuex.Store({
    namespaced: true,//解決模塊命名沖突
    actions,
    mutations,
    state,
})

注意:

我們在這一步創建index.js文件的時候導入並引用Vuex,因為我們要實例化Vuex對象。如果在main引入,會導致在main.js導入store的時候報錯。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-81CyZtfx-1634706841147)(image-20211019214509522.png)]

3.在main.js中引入上一步的index.js,並在實例化 Vue對象時加入 store 對象 :

import store from './store/index' //引入寫好的store
.....

new Vue({
 el: '#app',
 router,
 store,//使用store
 template: '',
 components: { App }
})

ok,環境搭好,開始操作。

4.簡單使用:

先來一點簡單的存放數據,取出查看。在一系列操作之后我們的VM(View Model)和VC(View component)身上都已經都有store這個數據源對象。所以我們可以從store身上使用this.$store.state.xxx獲取數據。

在index.js中准備數據

const state={
    name:'浪漫主義碼農',
    age:18,
}

在組件中獲取數據

<template>
  <div>
    我放在store中的數據是 {{this.$store.state.name}}, {{this.$store.state.age}}
  </div>
</template>

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-PdAMvoES-1634706841149)(image-20211020092641702.png)]

5.mutation、anction

在知道每一個vm和vc身上都有store就可以好好操作了。

mutation--更改store中狀態的唯一方法

根據上面的原理圖,我們能知道vuex中規定只能通過提交mutation的方式去更改store中的狀態,包括action中的操作,也是通過提交mutation去修改。另外一點就是vuex中規定mutation中不能包含異步操作

我們來修改上面的name、age屬性。

const mutations = {
    modify_age(state) {//不帶參數修改age屬性,state是默認的參數
        state.name = "張三";
        state.age = 20;
    },
    modify_age2(state,payload) {//帶參數修改,payload是傳入的對象,官網叫載荷(payload)
        state.name=payload.name;
        state.age=payload.age;
    }
}

在組件中,我們要使用this.$store.commit('xxx(方法名)', 參數;

參數可以是對象也可以是單一屬性

<template>
  <div>
    我放在store中的數據是 {{ this.$store.state.name }},
    {{ this.$store.state.age }}
    <button @click="setDefault">不帶參修改</button>
    <button @click="setparameter">帶參修改</button>
  </div>
</template>

<script>
export default {
  methods: {
    setDefault() {
      this.$store.commit("modify_age");
    },
    setparameter() {
    this.$store.commit("modify_age2",{name:"王五",age:100});//載荷形式,傳入可以使對象或者單個屬性
      // this.$store.commit({//對象形式,傳入可以使對象或者單個屬性
      //   type: "modify_age2",
      //   name: "王五",
      //   age: 100,
      // });
      });
    },
  },
};
</script>

在這里插入圖片描述

anction--同步/異步更改狀態

Action 類似於 mutation,不同在於:

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意異步操作。

后台API請求在這個模塊進行請求。所有的操作最后都要到達mutation進行操作,更改state的狀態。

還是上面一個例子,異步修改state的屬性

先上代碼

const actions = {
    asy_modify (context) {//無參
        setTimeout(() => {//異步操作
            context.commit("modify_age")
        }, 2000);
      },
      asy_modify2 (context,plyload) {//有參
        setTimeout(() => {
            context.commit("modify_age2",plyload);
        }, 2000);
      }
}
const mutations = {
    modify_age(state) {//不帶參數修改age屬性,state是默認的參數
        state.name = "張三";
        state.age = 20;
    },
    modify_age2(state,payload) {//帶參數修改,payload是傳入的對象,官網叫載荷(payload)
        state.name=payload.name;
        state.age=payload.age;
    }
}
const state = {
    name: '浪漫主義碼農',
    age: 18,
}

在組件中使用this.$store.dispatch('xxx')

<template>
  <div>
    我放在store中的數據是 {{ this.$store.state.name }},
    {{ this.$store.state.age }}
    <button @click="setDefault">不帶參修改</button>
    <button @click="setparameter">帶參修改</button>
  </div>
</template>

<script>
export default {
  methods: {
    setDefault() {
      this.$store.dispatch("asy_modify");
    },
    setparameter() {
      this.$store.dispatch("asy_modify2",{name:"王五",age:100});//載荷形式,傳入可以使對象或者單個屬性
      // this.$store.dispatch({//對象形式,傳入可以使對象或者單個屬性
      //   type: "asy_modify2",
      //   name: "王五",
      //   age: 100,
      // });
    },
  },
};
</script>

注意觀察時間,2s后變化。

在這里插入圖片描述

分析一波:

  1. Action 里面的函數接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調用 context.commit 提交一個 mutation,或者通過 context.statecontext.getters 來獲取 state 和 getters。

  2. action事件的觸發同樣可以使用載荷和對象兩種方式

6. getter

getter,我們可以理解為是對store中state的一些派生狀態,也可以理解為一種計算屬性,它類似於計算屬性一樣,返回值會根據它的依賴被緩存起來,且依賴對象發生改變的時候它才會被重新計算。

getter屬性相當於很多個組件需要對數據進行一樣的處理,可以理解為公共的計算屬性。

這樣就很清晰了

Getter 接受 state 作為其第一個參數,也可以使用箭頭函數。

const getters = {
    get_object: function (state) {//無參
        if (state.age < 18) {
            return state.name + '未成年'
        }
        return state.name + '已經成年了'
    },
    get_object2: function (state) {//有參數
        return function(value){
            return state.name + value;
        }
    }
}

組件中{this.$store.getters.xxx來獲取

<template>
  <div>
    我放在store中的數據是 {{ this.$store.state.name }},
    {{ this.$store.state.age }}
    <br>
    <span>不帶參數的數據:{{ this.$store.getters.get_object }}</span>
    <br>
    <span>帶參數的數據(攜帶一個剛好18歲):{{
        this.$store.getters.get_object2("剛好18歲")
      }}</span>
  </div>
</template>

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pB67ucIS-1634706841151)(image-20211020113845844.png)]

7.Modoules

Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊。這里就不過多介紹了,看官方文檔(Module | Vuex (vuejs.org))

8.輔助函數

vuex提供了幾個的輔助函數,有mapState、mapGetter、mapMutation、mapAction。都是一些復雜語句的簡寫形式。

引入函數

import {mapState,mapGetters,mapMutation,mapAction} from 'vuex'

mapState

如果state中的數據很多,那我們要重復寫很多這樣的this.$store.state.XXX代碼,我們就可以通過mapState來映射。

數組的寫法

export default {
  computed:{
    ...mapState(['name','age'])//自動就添加到了計算屬性中,此時就可以直接像訪問計算屬性一樣訪問它
  }
};

如果你想取名別名的話,就要寫成對象的形式

    ...mapState(
      {
        myname: 'name',
        myage: "age",
      } 

mapGetters

mapGetters和mapState很相似,只不過是映射Getters。替代this.$store.getters.XXX

computed: {
...mapGetters(['get_object','get_object2']),//數組形式寫法
    ...mapGetters({get1:'get_object',get2:'get_object2'})//可以取別名,對象形式寫法
  },

mapMutation

替代this.$store.commit('XXX')

  methods: {
    ...mapMutations(['modify_age','modify_age2']),//數組形式寫法
    ...mapMutations({modify:'modify_age',modify2:'modify_age2'}),//可以取別名,對象形式寫法
  },

mapAction

替代this.$store.dispatch('XXX')

  methods: {
    ...mapActions(['asy_modify','asy_modify2']),//數組形式寫法
...mapActions({act_modify:'asy_modify',act_modify2:'asy_modify2'})//對象形式寫法
  },

以上這些輔助函數,涉及到傳參都需在使用的計算屬性的時候傳入。

四、寫在最后

更具體的請看官網文檔,歡迎各位大佬指點江山。

看到最后點贊收藏吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM