一文學會使用Vuex

Vuex的使用

什麼是Vuex,這裏就不介紹了,請移步到官網 vuex.vuejs.org/zh/guide/ 學習,這裏咱們只須要知道Vuex能夠用來作應用的狀態管理。 首先來看一下使用vue create my-project命令生成項目的時候,自動生成的Vuex的代碼,store.js:vue

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {

  }
})

複製代碼

下面咱們來搞懂模版代碼中的state,mutations,actions是幹嗎的,既然Vuex能夠用來作狀態管理,那麼管理的是什麼?咱們知道vue是mvvm架構,想到mvvm 咱們就是想到數據驅動ui,因此,狀態管理,說白了管理的就是數據,那麼咱們就能夠把咱們須要操控的數據放在state裏面vuex

state

狀態,也就是存放咱們須要操控的數據數組

mutations

改變,若是咱們須要改變state中的數據的時候能夠在這裏面操做,怎麼操做?下面說bash

actions

行爲,和mutations相似,咱們想要改變state中的數據的時候能夠在這裏面進行操做,一樣,怎麼操做,下面說架構

既然是狀態管理,若是咱們直接操做state去改變他的值的話,固然就稱不上管理,Vuex採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化 ,固然不會直接讓咱們去修改state裏面的值。若是想要改變狀態的值怎麼辦,mutations登場:異步

store.js:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        userInfo: {}
    },
    mutations: {
        setUserInfo(state) {
            let info = {
                name: 'wfq',
                age: 26
            }
            state.userInfo = info
        }
    },
    actions: {}
})
複製代碼

而後在咱們的頁面上,咱們能夠這樣使用:mvvm

<template>
    <div>
        <div>name:{{$store.state.userInfo.name}}</div>
        <el-button type="primary" size="small" @click="$store.commit('setUserInfo')">獲取用戶信息</el-button>
    </div>
</template>

<script>
    export default {
        name: "vuex1",
        data() {
            return {}
        },
        methods: {},
        mounted() {
        }
    }
</script>

<style scoped>

</style>
複製代碼

使用$store.commit('setUserInfo')來觸發mutations中的getUserInfo方法,對於mutations,這裏有幾點須要注意:ide

  • mutations 中的方法是不分組件的,若是在多個組件中都有setUserInfo,那麼執行$store.commit('setUserInfo')的時候會把全部組件中的這個方法都執行,
  • mutations 中的方法最好是同步的,異步的方法有什麼問題?沒什麼問題,可是官方建議咱們將異步的操做放在actions裏面去操做

多個 state 的操做 , 使用 mutations 會來觸發會比較好維護 , 那麼須要執行多個 mutations怎麼辦?actions登場,前面說過 官方建議咱們在actions裏面寫異步的代碼,那麼咱們模擬一下:函數

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

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        userInfo: {}
    },
    mutations: {
        setUserInfo(state,userInfo) {
            state.userInfo = userInfo
        }
    },
    actions: {
        // commit來自Vuex中上下文context,這裏直接使用對象解構,至關於context.commit('setUserInfoAsync',info)
        setUserInfoAsync({commit}){
            setTimeout(()=>{
                let info = {
                    name: 'wfq',
                    age: 26
                }
                commit('setUserInfo',info)
            },2000)
        }
    }
})

複製代碼

在store.js中咱們在actions中使用commit來觸發mutations裏面的方法,這個和上面說的一致,那麼咱們怎麼觸發actions裏面的方法:學習

<template>
    <div>
        <div>name:{{$store.state.userInfo.name}}</div>
        <el-button type="primary" size="small" @click="$store.dispatch('setUserInfoAsync')">獲取用戶信息</el-button>
    </div>
</template>
複製代碼

咱們使用dispatch來觸發actions裏面的方法。

總結

  1. 爲何咱們在頁面能夠直接使用this.$store來觸發store.js裏面的代碼,由於咱們在main.js構建vue的實例的時候已經將store.js引入
  2. state好理解,那麼我什麼時候該使用mutations,什麼時候該使用actions? 同步的方法,咱們放在mutations裏面,異步的代碼咱們放在actions裏面, 觸發mutations裏面的方法,咱們使用commit,觸發actions裏面的方法咱們使用dispatch 3.注意:咱們在actions裏面的方法,是已經默認攜帶了上下文context的,固然使用對象解構的話,咱們能夠直接使用以下方法來書寫代碼: functionName({commit,dispatch},param1,param2...){}

mapState、mapGetters、mapActions

若是咱們調用方法,頁面上過分使用this.$store.***的話,會顯得很累贅,上面三個函數即是Vuex給咱們提供的函數,方便咱們調用store裏面的方法 首先記住一點,mapstate和mapGetters放在computed中,mapActions放在methods,記得導入mapState,mapGetters,mapActions,那麼咱們以前頁面的代碼能夠改寫以下:

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

export default new Vuex.Store({
    state: {
        userInfo: {}
    },
    getters:{
        getUserInfo(state){
            return state.userInfo
        }
    },
    mutations: {
        setUserInfo(state,userInfo) {
            state.userInfo = userInfo
        }
    },
    
    actions: {
        // commit來自Vuex中上下文context,這裏直接使用對象解構,至關於context.commit('setUserInfoAsync',info)
        setUserInfoAsync({commit}){
            setTimeout(()=>{
                let info = {
                    name: 'wfq',
                    age: 26
                }
                commit('setUserInfo',info)
            },2000)
        }
    }
})

複製代碼
頁面
<template>
    <div>
        <div>name:{{userInfo.name}}</div>
        <el-button type="primary" size="small" @click="getInfo">獲取用戶信息</el-button>
    </div>
</template>

<script>
    import {mapState,mapGetters,mapActions} from 'vuex'
    export default {
        name: "vuex1",
        data() {
            return {}
        },
        computed:{
        // 這裏的mapState對應store.js裏面的state,參數是個數組,裏面的元素其實就是store.js裏面的state裏面的數據
            ...mapState([
                'userInfo'
            ]),
        // 這裏的mapGetters對應store.js裏面的getters,參數是個數組,裏面的元素其實就是store.js裏面的getters裏面的方法
        // mapGetters其實和mapState相似,都是獲取state裏面的數據,大多數狀況,咱們使用mapState便可,這也是爲何state.js的
        // 模版代碼中沒有getters
            ...mapGetters([
                'getUserInfo'
            ])
            
        },
        methods: {
        // 這裏的mapActions對應的是store.js裏面的actions,參數是個數組,裏面的元素其實就是store.js裏面的actions裏面的方法           
            ...mapActions([
                'setUserInfoAsync'
            ]),
            getInfo(){
            // 調用的方法是mapActions裏面的setUserInfoAsync
                this.setUserInfoAsync()
            },
        },
        mounted() {
        }
    }
</script>

<style scoped>

</style>
複製代碼

思考一個問題:若是咱們應用須要狀態管理的數據過多的時候,寫在一個store裏面的話就顯得太累贅,怎麼處理?

這裏咱們使用了Vuex的modules,以及namespaced屬性,modules容許咱們以modules的形式導出多個store,namespaced:true的話表明 咱們訪問store裏面的方法時要在對應的命名空間下

下面咱們改寫代碼,新建store文件夾,在下面新建index.js和modules文件夾,在modules文件夾下面新建一個咱們本身須要的文件夾wfq, 而後在wfq下面新建modules文件夾和index.js,而後在main.js裏修改store的路徑,目錄結構以下圖

代碼以下:

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import wfq from './modules/wfq'
Vue.use(Vuex)

export default new Vuex.Store({
    modules: {
        wfq
    }
})
複製代碼

store/modules/wfq/index.js

// 找出以.js開頭的文件
const files = require.context('./modules', false, /\.js$/)
const modules = {}
files.keys().forEach(key => {
    modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
export default {
    namespaced: true,
    modules
}


複製代碼

store/modules/wfq/modules/user.js

export default {
    namespaced: true,
    state: {
        userInfo: {name:'WFQ'}
    },
    getters:{
        getUserInfo(state){
            return state.userInfo
        }
    },
    mutations:{
        setUserInfo(state,info){
            state.userInfo = info
        }
    },
    actions: {
        
        setUserInfoAsync({commit}){
            setTimeout(()=>{
                let info = {
                    name: 'wfq',
                    age: 26
                }
                commit('setUserInfo',info)
            },2000)
        }
    }
}

複製代碼

接下來看咱們怎麼使用:

<template>
    <div>
        <div>name:{{userInfo.name}}</div>
        <el-button type="primary" size="small" @click="setInfo">設置用戶信息</el-button>
    </div>
</template>

<script>
    import {mapState,mapActions} from 'vuex'
    export default {
        name: "demo1",
        data() {
            return {}
        },
        computed:{
            ...mapState('wfq/user',[
                'userInfo',
            ]),
        },
        methods: {
            ...mapActions('wfq/user',[
                'setUserInfoAsync',
            ]),
            setInfo(){
                this.setUserInfoAsync();
            },
        },
        mounted() {
        }
    }
</script>

複製代碼

使用modules修改後,mapState和mapActions要在第一個參數加上路徑,'wfq/user',這也就證實了namespaced的做用

接下來再思考一個問題,若是我在一個store文件(例如user.js)裏面想調用另外一個store的方法怎麼辦,好比,在獲得用戶的信息後, 我想直接調用該用戶的訂單信息,而後存儲在vuex中怎麼辦?咱們知道,獲取訂單信息是一個異步操做,咱們要放在actions裏面,而actions裏面的 方法怎麼觸發呢?使用dispatch 咱們新建一個store文件,order.js,此時目錄結構以下圖

代碼以下:

export default {
    namespaced: true,
    state: {
        orderList:[]
    },
    getters:{

    },
    mutations:{

    },
    actions: {
        setOrderListByUser({state},userInfo){
            if(userInfo.name === 'wfq'){
                let orderlist = ['order1','order2']
                state.orderList = orderlist
            }

        }

    }
}
複製代碼

下面咱們修改user.js的代碼以下:

actions: {
        
        setUserInfoAsync({commit,dispatch}){
            setTimeout(()=>{
                let info = {
                    name: 'wfq',
                    age: 26
                }
                commit('setUserInfo',info)
                dispatch('wfq/order/setOrderListByUser',info,{ root: true })
            },2000)
        }
    }
複製代碼

咱們使用dispatch來觸發order下面的setOrderListByUser的方法,並傳入用戶信息,注意:這裏要設置{ root: true }, 這樣咱們就能在別的頁面獲取到order.js裏面的state下面的orderList的數據了,注意:別忘了去main.js裏面修改store的路徑

相關文章
相關標籤/搜索