巧學vuex

IT男爵發表於2018-11-30

"Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化"。這句話是擷取vuex官網上對vuex介紹的一句話,對於很多新手朋友,剛接觸vuex的時候,肯定被它這麼多的專業詞彙搞得一臉懵逼,不知所云。那麼作為新手該如何學習vuex呢,我的建議就是“理解”,用通俗易懂的話和比喻來說明vuex是個幹啥的,是個什麼東西。

vuex

上面的前言,說了要用通俗易懂的話來介紹vuex,那麼該怎麼理解呢?我的理解就是,你把vuex當成一個專案頂層的全域性物件來看待,有了這樣的認識,你在學習vuex肯定會事半功倍的。

安裝vuex

首先我們要安裝:

`

npm install vuex --save
複製程式碼

`

其次就是建立vuex,建立這一塊建議大家按照官方的文件命名來,這樣做的目的嗎,顯而易見,大家都知道開發當中有一些潛在的規範,遵守這些規範就是為了讓大家好理解,我這裡是幹嘛的。在這裡我就建議大家在專案裡單獨建立一個store的資料夾,並在裡面建立一個index.js的檔案吧,然後在index.js裡引入vuex:

`

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

// 這個是store資料夾下的index.js檔案
export default new Vuex.Store({ // 匯出這個物件
    state: {
        
    },
    getters: {

    },
    mutations: {
        
    },
    actions: {
        
    }
})
複製程式碼

`

最後在main.js的檔案裡引入我們剛建立的store資料夾裡的index.js檔案:

`

import Vue from 'vue';
import App from './App';
import router from './router';
import store from './store/index';  // 引入vuex

new Vue({
  el: '#app',
  router,
  store, // 注入vuex 
  components: { App },
  template: '<App/>'
})
複製程式碼

`

到這一步,我們的vuex就算是搭建完畢了,下面我們就針對vuex裡的各個功能模組進行探討,vuex下面有四個功能模組state, getters, mutations, actions,也就是四個子物件。

State

前面我們說了vuex其實就是一個全域性物件,而這個物件呢包含有四個子物件,子物件一:statestate是幹嘛的呢?,state就是這個全域性物件專門用來儲存資料的地方,也就是公共的資料來源:

`

export default new Vuex.Store({ 
    state: { // 這裡是儲存資料的地方,公共的資料來源
        animals: [{num: 1, animal: '老虎'}, {num: 2, animal: '獅子'},
        {num: 3, animal: '大象'}]
    }
})
複製程式碼

`

那麼如何使用這個資料呢?使用很簡單,直接在vue裡的computed物件裡書寫即可:

`

// 組建裡呼叫
<template>
    <div>
        <ul>
            <li v-for="(item,index) in animals" :key="index">
                <label>{{item.num}}</label>
                <span>{{item.animal}}</span>
            </li>
        </ul>
    </div>
</template>

// ...其他程式碼省略
computed: {
    animals () {
            return this.$store.state.animals;
        }
}
複製程式碼

`

注意:this.$store就是我們整個vuex例項,也就是我們說的那個全域性物件,state就是儲存公共資料的容器。 這樣我們就成功的使用到了vuex state裡的資料了。

Getter

子物件二:getter,它的功能和作用就類似於vue裡的computed,也就是說vuex裡的計算屬性,vue裡的computed是用來對資料進行額外操作的,vuex裡的getter也是一樣的:

`

export default new Vuex.Store({ 
    state: { // 這裡是儲存資料的地方,公共的資料來源
        animals: [{num: 1, animal: '老虎'}, {num: 2, animal: '獅子'},
        {num: 3, animal: '大象'}] 
    },
    getter: {
        filterAnimal: state => {    // 這是個方法
            return state.animals.filter(item => {
                return item.num > 1
            })
        }
    }
})
複製程式碼

`

注意:getter裡面filterAnimal是個方法,方法名字隨你自己定義,state這個引數就是vuex儲存資料裡的state,getter裡所有的方法都預設傳入了該引數。 使用也是直接在vue裡的computed物件裡書寫:

`

// 組建裡呼叫
<template>
    <div>
        <ul>
            <li v-for="(item,index) in filterAnimal" :key="index">
                <label>{{item.num}}</label>
                <span>{{item.animal}}</span>
            </li>
        </ul>
    </div>
</template>

// ...其他程式碼省略
computed: {
    filterAnimal () {
            return this.$store.getters.filterAnimal;
        }
}
複製程式碼

`

Mutations

子物件三:mutations,官網裡是這樣介紹的:“更改 Vuex 的 store 中的狀態的 唯一 方法是提交 mutation”,在這段話裡面請大家注意那個“唯一”。這也就是說,對vuexstate裡面的資料,你要想進行修改,必須通過mutations方式才可以,只有mutations這個物件裡的方法才可以修改state裡的資料,也就是狀態:

`

export default new Vuex.Store({ 
    state: { // 這裡是儲存資料的地方,公共的資料來源
        animals: [{num: 1, animal: '老虎'}, {num: 2, animal: '獅子'},
        {num: 3, animal: '大象'}] 
    },
    mutations: {
        addAnimal (state, params) { // params是來自你呼叫這個方法時傳入的引數
            state.animals.push(params)
        }
    }
})
複製程式碼

`

注意:mutations裡定義的方法可以接收兩個引數,state就是資料物件,params就是呼叫時傳遞過來的資料

組建裡呼叫mutations裡的方法,使用this.$store.commit()觸發,引數一是你要觸發的mutations裡的哪個方法,引數二就是你要傳遞過去的資料: `

// 組建裡呼叫
<template>
    <div>
        <button @click="addAnimal()">增加動物</button>
        <ul>
            <li v-for="(item,index) in filterAnimal" :key="index">
                <label>{{item.num}}</label>
                <span>{{item.animal}}</span>
            </li>
        </ul>
    </div>
</template>

// ...其他程式碼省略
methods: {
    addAnimal () {
            let animal = {num: 4, animal: '熊貓'}
            this.$store.commit('addAnimal', animal);
        }
}
複製程式碼

`

mutations操作注意事項:mutations屬於同步操作,所以你在操作時請記得提前宣告好你要操作的資料,也就是state裡的資料

Actions

子物件四:actions類似於mutationsactions的不同點有兩點:

  • action 提交的是 mutation,而不是直接變更狀態;
  • action 可以包含任意非同步操作;

大家請記住上面這兩點,上面介紹mutations時說過,要想改變state裡面的資料,唯一的方法就是通過mutations,所以action這裡也是通過mutation: `

export default new Vuex.Store({ 
    state: { // 這裡是儲存資料的地方,公共的資料來源
        animals: [] 
    },
    mutations: {
        initAnimal (state, params) { // 初始化state裡animals資料
            state.animals = params;
        }
    },
    actions: {
        initAnimals (context) {
            return new Promise((resolve, reject) => {
                let animals = [{num: 1, animal: '老虎'}, {num: 2, animal: '獅子'},
                              {num: 3, animal: '大象'}]
                context.commit('initAnimal', animals);  //呼叫mutations裡的方法
                resolve(animals);
            })
        }
    }
})
複製程式碼

`

組建裡面呼叫,使用vuex裡的this.$store.dispatch()方法執行,上面例子中的Promise並沒有實際意義,只是為了演示特意寫出來的,你方法體裡直接寫context.commit()也是可以的:

`

// 組建裡呼叫
// ...其他程式碼省略
created() {
    this.$store.dispatch('initAnimals');
}
複製程式碼

` 在本示例中,呼叫是在組建生命週期鉤子函式裡呼叫,具體在什麼地方呼叫,根據實際的業務需求去實現即可。

mapState、mapGetters、mapActions

mapState、mapGetters、mapActions這三個是vuex裡簡化呼叫而提供的方法,你如果需要使用,需要在你使用的組建單獨引入這三個方法:

`

// 組建裡呼叫
<template>
    <div>
        <ul>
            <li v-for="(item,index) in animals" :key="index">
                <label>{{item.num}}</label>
                <span>{{item.animal}}</span>
            </li>
        </ul>
    </div>
</template>

// ...其他程式碼省略
import {mapState, mapGetters, mapActions} from 'vuex';

computed: {
    // 使用擴充套件運算子
    ...mapState({
        animals:state => state.animals
    }),
}
複製程式碼

`

這裡暫且只示例mapState了,其他留給大家自己嘗試,稍微說明應用的地方,mapGetters一般也是在computed裡呼叫,mapActions一般是在methods的方法裡呼叫。

Module

看完上面的內容,其實大家已經會使用vuex了,那麼這個Module是幹嘛的呢,上面我們說過,vuex是老頂層的全域性物件,如果所有的資料狀態如果都寫在這個index的檔案裡面,程式碼體會越來越大,所以,vuex允許我們把store分割成各自獨立的模組,每個獨立模組都有自己的state, getters, mutations, actions,注意哦,分割出去的各個模組,他們的state裡的資料都是獨立,各自是各自的。:

`

import Vue from 'vue';
import Vuex from 'vuex';
import module1 from './modules/module1';
import module2 from './modules/module2';

// 這個是vuex的主模組,也就是index.js這個檔案
export default new Vuex.Store({
state,
mutations,
actions,
modules: {
    module1,
    module2
}
複製程式碼

}) `

獨立出去的模組使用import引入進來,在主模組裡在modules裡注入即可。

總結

在本篇文章的思路里,是以全域性物件的思維方式來學習vuex,其目的也是為了讓大家更快速的理解和認識vuex,那麼vuex是否就是全域性物件呢,在vuex的官方文件裡就已經給出了答案和解釋:

  • Vuex 的狀態儲存是響應式的。當 Vue 元件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的元件也會相應地得到高效更新。
  • 你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用。

vuex的主要應用就是對多組建或者多頁面使用同一個資料來源,也就是說共用同一個資料,當我們在某一個組建改變這個資料的某一個狀態或者值時,相應的也讓其他組建和頁面發生相同的變化。 最後也把vuex官網的連結貼在這裡,大家看完後可以在去官網檢視實際API。

相關文章