筆記整理 vuex

初識 vuex

寫在前面vue

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

我爲何使用vuexvuex

當咱們的應用遇到多個組件共享狀態時 Vuex 能夠幫助咱們管理共享狀態axios

本筆記只作參考, 官方學習入口點擊這裏api

不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。bash

一個簡單地 vuex

預熱前奏app

// store.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)

const state = {} // 數據倉庫
const mutations = {}    // 操做方法
const actions = {}  // 操做方法命令
const getters = {}  // 數據計算

export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})
複製代碼

這幾個屬性是幹啥玩意兒呢?異步

state 倉庫數據,用於存儲數據async

mutations 操做倉庫數據的方法集合,建議用於對倉庫單個數據的操做模塊化

actions 派發事件 | 可執行的其餘操做 | 可用異步代碼或多個事件派發【簡言之: 生而爲數據的複雜操做】

getters 倉庫數據的計算屬性,形如組件中的 computed 的使用

以上是一個基本的 vuex 倉庫,要想在項目中使用,咱們還須要在 main.js 中引入並掛載

// main.js
import store from "./store.js"  // 引入

new Vue({
  store,    // 掛載
  render: h => h(App)
}).$mount("#app");
複製代碼

爲了更加清晰地使用vuex,咱們初步對文件代碼進行分離

分離 & 使用

分離

# 目錄
|-- store
    |-- index.js
    |-- state.js
    |-- mutations-type.js
    |-- mutations.js
    |-- actions.js
複製代碼

index.js 使用 vuex 入口

import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import * as getters from './getters'
import * as actions from './actions'

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  mutations,
  getters,
  actions
})
複製代碼

state.js 數據集結地

const state = {
    list: [],
    tempList: []
}

export default state
複製代碼

mutations-type.js 事件名

export const SET_LIST = 'SET_LIST'
export const SET_TEMP_LIST = 'SET_TEMP_LIST'
複製代碼

mutations.js 管家

import * as types from './mutations-type'
const mutations = {
    /************************************* *** 變動state中的某數據狀態 *************************************/
    [types.SET_LIST](state, list) {
        state.list = list
    },
    [types.SET_TEMP_LIST](state, list) {
        state.tempList = list
    }
}
export default mutations
複製代碼

actions.js 帶Buff的管家

import axios from "axios";
import * as types from "./mutations-type";
export const actions = {
    /**************************************** *** 可包含任何異步請求 *** 多重命令mutation, 並不是直接變動數據 ****************************************/
    async getListAndSet({ commit }, queryParams) {
        const ret = await axios.get('api/test/test1', {
            params: queryParams
        }).then(res => res.data.data)
        commit(types.SET_LIST, ret)
        commit(types.SET_TEMP_LIST, ret)
        localStorage.setItem('_list', ret)
    }
}
    
複製代碼

getters.js 數據計算輸出

export const list = state => state.list
export const tempList = state => state.tempList
export const whiteUser = state => state.list.filter(item => (/白/g).test(item.nickname)) 
複製代碼

使用 & 輔助函數

.vue 中使用 vuex 數據, 咱們能夠在計算屬性(computed)中先定義

computed: {
    list() {
        return this.$store.getters.list;
    },
    tempList() {
        return this.$store.getters.tempList;
    },
    whiteUser() {
        return this.$store.getters.whiteUser;
    }
}
複製代碼

再後來於組件中正常訪問便可

<template>
    <div class = "list">
        <div class="item" v-for="(user, index) in list" :key="index"> {{ user.nickname }} </div>
    </div>
</template>
複製代碼

組件中提交 mutations & 分發 actions

export default {
    methods: {
        setListData() {
            const data = [
                { nickname: '小白1', age: 18 }, 
                { nickname: '小白2', age: 17 }, 
                { nickname: '小黑', age: 19 }
            ]
            // 組件中 提交 mutations
            this.$store.commit("SET_LIST", list);
        },
        getListAndSetData() {
            // 組件中 分發 actions 
            this.$store.dispatch("getListAndSet", {
                page: 1,
                limit: 20
            });
        }
    }
}
複製代碼

輔助函數 映射 vuex 數據/方法到局部組件中【喜歡就用: 推薦

  • mapMutations
  • mapActions
  • mapGetters
  • ...
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
    methods: {
        setListData() {
            const data = [
                { nickname: '小白1', age: 18 }, 
                { nickname: '小白2', age: 17 }, 
                { nickname: '小黑', age: 19 }
            ]
            this.SET_LIST(list);
        },
        getListAndSetData() {
            this.getListAndSet({
                page: 1,    
                limit: 20
            });
        },
        // mapMutations & mapActions 都在 methods 中進行映射
        ...mapMutations(["SET_LIST"]),
        ...mapActions(["getListAndSet"])
    },
    computed: {
        // mapState & mapGetters 都在 computed 中進行映射
        ...mapGetters(["list", "tempList", "whiteUser"])
    }
}
複製代碼

輔助函數參數還能夠是對象

export default {
    methods: {
        setListData() {
            const data = [
                { name: '小白1', age: 18 }, 
                { name: '小白2', age: 17 }, 
                { name: '小黑', age: 19 }
            ]
            this.setList(data)    // 提交 mutations 設置列表數據
        },
        // 輔助函數接收對象形式,其它函數形式也是如此
        ...mapMutations({
            setList : 'SET_LIST',
        })
    }
}
複製代碼

若是項目夠大/複雜 vuex 的 Module 就能夠發揮巨大做用

模塊化(全局命名空間)

# 基本目錄結構
|-- store
    |-- modules
        |-- global.js
        |-- test.js
    |-- index.js
    |-- types.js

# 固然, 咱們能夠細分每一個模塊
複製代碼

store 入口文件

import Vue from 'vue'
import Vuex from 'vuex'
// 管理模塊
import test from './modules/test'
import global from './modules/global'

Vue.use(Vuex)
const store = new Vuex.Store({
  modules: {
    test,
    global
  },
})
export default store;
複製代碼

types.js

export const SET_LIST = 'SET_LIST';
export const SET_TEMP_LIST = 'SET_TEMP_LIST';

// global
export const SET_TOKEN = 'SET_TOKEN'
複製代碼

modules/test.js

// test module 
import * as types from '../types';
import axios from "axios"

const state = {
    list: [],
    tempList: []
}

const mutations = {
    [types.SET_LIST](state, list) {
        state.list = list
    },
    [types.SET_TEMP_LIST](state, list) {
        state.tempList = list
    }
}

const actions = {
    async getListAndSet({ commit }, queryParams) {
        const ret = await axios.get('api/test/test1', {
            params: queryParams
        }).then(res => res.data.data)
        commit(types.SET_LIST, ret)
        commit(types.SET_TEMP_LIST, ret)
        localStorage.setItem('_list', ret)
    }
}

const getters = {
    list: state => state.list,
    tempList: state => state.tempList,
    whiteUser: state => state.list.filter(item => (/白/g).test(item.nickname))
}

export default {
    state,
    actions,
    getters,
    mutations
}
複製代碼

全局命名空間 的模塊化,咱們能夠按照以往方式正常得到屬性或方法, 由於它們都默認被註冊於全上.


考慮模塊理應具備封裝/複用性, 不喜歡命名上有所衝突, 因此

模塊化 & namespace

爲 vuex 模塊添加命名空間時,咱們須要探討的幾個問題

  • 如何給 vuex 模塊添加命名空間
  • 在帶命名空間的模塊中訪問全局命名空間內容
  • 添加了命名空間的模塊在組件中訪問方式

給vuex模塊添加命名空間&訪問全局命名空間內容

/** * 添加命名空間的vuex模塊的actions&getters的參數對象選項中會自動添加 rootState/rootGetters 方便咱們訪問全局屬性 * 添加命名空間的vuex模塊的actions中想要訪問全局下的 dispatch 或 commit, 須要賦予第三個參數 { root: true } 表示受權 */

import * as types from '../types';
import axios from "axios"

const state = {
    listNameSpace: []
}

const mutations = {
    ["SET_LIST"](state, list) {
        state.listNameSpace = list
    }
}

const actions = {
    // 帶命名空間的 module 中 dispatch 和 commit 都被局部化,能夠經過第三個參數對象 {root: true} 訪問
    // 參數對象中會自動添加參數 rootState rootGtters, 分別表示全局下的數據 
    async getListAndSetNamespace({
        dispatch,
        commit,
        rootState,
        rootGetters
    }, queryParams) {
        const ret = await axios.get('api/test/test1', {
            params: queryParams
        }).then(res => res.data.data)
        commit('SET_LIST', ret) // 訪問局部的 test_namespace/SET_LIST 
        commit("SET_LIST", ret, { root: true }) // 訪問全局下的 SET_LIST
        dispatch("getListAndSet", ret, { root: true }) // 訪問全局下的 getListAndSet

        console.log('rootState: ', rootState)
        console.log('rootGetters: ', rootGetters)
    }
}

const getters = {
    // 帶命名空間的 module 中 state 和 getters 都被局部化, 會自動添加 第三個參數(rootState)第四個參數(rootGetters)能夠經過它們訪問全局屬性
    ListNameSpaceGetters(state, getters, rootState, rootGetters) {
        return rootGetters.tempList
    }
}

export default {
    namespaced: true,
    state,
    actions,
    getters,
    mutations
}
複製代碼

在組件中訪問帶命名空間的vuex模塊

<template>
    <div>
        ListNameSpaceGetters: {{ ListNameSpaceGetters }}
        <van-button @click="namespaceGetDataAndSetData">局部組件的actions調用</van-button>
    </div>
</template>
複製代碼
import { mapGetters, mapActions } from "vuex";
export default {
  name: "test",
  data() {
    return {};
  },
  methods: {
    namespaceGetDataAndSetData() {
        this.getListAndSetNamespace()
    },
    
    ...mapActions({
        getListAndSetNamespace: 'test_namespace/getListAndSetNamespace'
    })
  },
  computed: {
    ...mapGetters({
        listNameSpaceGetters: "test_namespace/ListNameSpaceGetters"
    })
  }
};
複製代碼

vuex 日誌使得咱們能夠在 console 愉快地查看對 vuex 的操做

vuex 日誌

// store 入口文件中添加 4 行代碼
import Vue from 'vue'
import Vuex from 'vuex'

// 管理模塊
import test from './modules/test'
import global from './modules/global'

import createLogger from 'vuex/dist/logger' // 1

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production' // 2

const store = new Vuex.Store({
  modules: {
    test,
    global
  },
  // vuex工具
  strict: debug,    // 3
  plugins: debug ? [createLogger()] : []    // 4
})

export default store;

複製代碼

結語

筆記僅供參考, 若有錯誤還請朋友們不吝指出.

相關文章
相關標籤/搜索