Vuex 狀態(tài)管理的基本使用配置

vuex流程圖

1.安裝Vue 依賴包

npm install vuex@3 --save
vue2 只能用vuex的3版本
vue3 只能用vuex的4版本
npm view vuex versions 查看vuex所有版本

2.創(chuàng)建 store

src目錄下 新建 store 目錄 鳖昌,創(chuàng)建 index.js 文件

// 引入 vue
import Vue from 'vue'

// 引入 vuex
import Vuex from 'vuex'

// 使用Vuex
Vue.use(Vuex)

// 用于存儲(chǔ)數(shù)據(jù)
const state = {}

// 用于響應(yīng)組件中的動(dòng)作
const actions = {}

// 用于操作數(shù)據(jù)(state)
const mutations = {}

// 創(chuàng)建store
const store = new Vuex.Store({
    state,
    mutations,
    actions
})

// 導(dǎo)出 store
export default store;

3.引入store

main.js 中 引入 import store from './store'
配置 store

new Vue({
   el: '#app',
   render:h => h(App),
   router,
   //將創(chuàng)建的共享數(shù)據(jù)對象,掛載在vue實(shí)例中
   //所有的組件患亿,就可以直接從store中獲取全局的數(shù)據(jù)了
   store
})

Vuex 應(yīng)用

state

作用:獲取數(shù)據(jù)

獲取state數(shù)據(jù)的第一種方式

this.$store.state.全局?jǐn)?shù)據(jù)名稱

第二種方式

從vuex中按需導(dǎo)入mapState 函數(shù)

import { mapState } from 'vuex'

通過剛才導(dǎo)入的mapState 函數(shù)盲链,將當(dāng)前組件需要的全局?jǐn)?shù)據(jù)壕吹,映射為當(dāng)前組件的computed計(jì)算屬性

computed: { 
   //數(shù)組寫法  count 是store中全局共享數(shù)據(jù)名稱   獲取store中的數(shù)據(jù)
    ...mapState(['count'])
   // 對象寫法
   ...mapState({count:'count',...})
}

mutations

作用:修改全局state中的數(shù)據(jù)(用于操作數(shù)據(jù))

只能 通過 mutations 修改 state 中的數(shù)據(jù)所踊,可以集中監(jiān)控所有數(shù)據(jù)的變化。不可以直接操作 store 中的數(shù)據(jù)恼布。
mutations里面方法名稱一般大寫螺戳,方法第一個(gè)參數(shù)永遠(yuǎn)都是一個(gè) state 代表全局對象,直接state.屬性就可以調(diào)用全局共享數(shù)據(jù)的屬性,

const mutations = { 
    // value 參數(shù)
    INCRE(state, value) {
        state.sum += value
    },

    DECRE(state, value) {
        state.sum -= value
    }
}

觸發(fā)mutation 的第一種方式

不傳參數(shù):this.$store.commit('方法名') add 是Mutation中定義的函數(shù)名
傳參數(shù) : this.$store.commit('方法名',參數(shù))

觸發(fā)mutation 的第二種方式
vuex 中按需導(dǎo)入 mapMutations 函數(shù)

import { mapMutations } from 'vuex'

通過剛才導(dǎo)入的 mapMutations 函數(shù)折汞,將需要的 mutations倔幼,映射為當(dāng)前組件的 methods 方法

 methods: {
    // 數(shù)組寫法   吧全局mutations里面的sub、subN函數(shù)映射為當(dāng)前組件的methods (如果有參數(shù)需要觸發(fā)的時(shí)候傳過來)
    ...mapMutations(['sub', 'subN']), 
    // 對象寫法 (如果有參數(shù)需要觸發(fā)的時(shí)候傳過來)
    ...mapMutations({sub:'sub', subN:'subN'}), 
 }
    
 this.sub();//可以直接調(diào)用
 this.subN();//可以直接調(diào)用

注意:在 mutations 中不要執(zhí)行異步操作爽待,mutations里面只處理簡單方法损同,沒有業(yè)務(wù)邏輯的

actions

作用:用于處理異步任務(wù)

如果通過異步操作變更數(shù)據(jù),必須通過 action 鸟款,而不能使用 Mutation膏燃,但是在 Action 還是要通過觸發(fā) Mutation 的方式間接變更數(shù)據(jù)

action方法第一個(gè)參數(shù)永遠(yuǎn)都是一個(gè) context 相當(dāng)于new出來的 store 的實(shí)體對象

修改state中的數(shù)據(jù)必須通過 mutations

觸發(fā)Actions 的第一種方式

this.$store.dispatch('方法名')  //addAsync adction中的函數(shù)  dispatch函數(shù) 專門用來觸發(fā) action

觸發(fā)Actions 的第二種方式
從vuex中按需導(dǎo)入 mapActions 函數(shù)

import { mapActions } from 'vuex'

通過剛才導(dǎo)入的 mapActions 函數(shù),將需要的 actions 函數(shù) 何什,映射為當(dāng)前組件的methods方法

 methods: {
    // 數(shù)組方式 (方法名稱必須和vuex里面的方法相同)
    ...mapActions(['方法名1', '方法名2'])
    // 對象方式
    ...mapActions({ 方法名1: 'action里面的方法名1',方法名2: 'action里面的方法名2' })
 }

getters

作用: 包裝作用组哩,不會(huì)修改數(shù)據(jù)(用于 state 中數(shù)據(jù)加工)

在getters中定義一個(gè)函數(shù)

//定義函數(shù)
showNum(state) {
    return '當(dāng)前最新數(shù)據(jù)是[' + state.count + ']'
}

使用getters第一種方式

this.$store.getters.名稱
this.$store.getters.showNum

使用getters第二種方式

從vuex中按需導(dǎo)入 mapGetters 函數(shù)

//組件訪問state中數(shù)據(jù)的第二種方式 先導(dǎo)入
import { mapGetters } from 'vuex';

通過剛才導(dǎo)入的mapGetters函數(shù),將當(dāng)前組件需要的全局?jǐn)?shù)據(jù)处渣,映射為當(dāng)前組件的computed計(jì)算屬性

 computed: { 
    // 數(shù)組寫法(方法名稱必須和vuex里面的方法相同)
    ...mapGetters(['方法名']),
    // 對象寫法
    ...mapGetters({ 方法名: 'getter里面的方法名稱' })
  }

vuex 模塊化+命名空間

目的:代碼更好維護(hù)伶贰,讓多種類數(shù)據(jù)更加明確

開啟命名空間后,讀取 state 數(shù)據(jù)

this.$store.state.countAbout.sum  // 直接的讀取
...mapState('countAbout', ["sum", "school", "subject"]) // 借助mapState讀取

開啟命名空間后罐栈,讀取 getters 數(shù)據(jù)

this.$store.getters[countAbout/bigSum] // 直接的讀取
...mapGetters('countAbout', ['bigSum']) //借助mapGetters讀取

開啟命名空間后黍衙,讀取 dispatch 數(shù)據(jù)

this.$store.dispatch('countAbout/increOdd', val) // 直接的讀取
...mapActions('countAbout', { handleIncreOdd: 'increOdd', handleIncreWait: 'increWait' }) // 借助 mapActions 讀取

開啟命名空間后,讀取 commit 數(shù)據(jù)

this.$store.commit('countAbout/INCRE', val) // 直接的讀取
...mapMutations('countAbout', { handleIncre: 'INCRE', handleDecre: 'DECRE' }) // 借助 mapMutations 讀取

store/index.js

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

import countOptions from "./modules/count"
import personOptions from "./modules/person"

// 創(chuàng)建store并導(dǎo)出 store
export default new Vuex.Store({
    modules: {
        countAbout: countOptions,
        personAbout: personOptions
    }
})

store/modules/count.js

count.js

Demo1 ==> 計(jì)數(shù)

Count.vue

<template>
  <div>
    {{sum}}
    <p>getters:{{bigSum}}</p>
    <p> {{school}}, {{subject}}</p>
    <button @click="handleIncre(2)">+2</button>
    <button @click="handleDecre(3)">-3</button>
    <button @click="handleIncreOdd(1)">奇數(shù)加1</button>
    <button @click="handleIncreWait(1)">1s后+1</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex"
export default {
  computed: {

    // sum() {
    //   return this.$store.state.sum
    // },

    // ...mapGetters(['bigSum']),//數(shù)組寫法
    ...mapGetters({ bigSum: 'bigSum' }), // 對象寫法

    // ...mapState(["sum", "school", "subject"])  //數(shù)組寫法
    ...mapState({ sum: "sum", school: "school", subject: "subject" })  // 對象寫法

  },
  methods: {
    // 寫法一
    // handleIncre(val) {
    //   this.$store.commit('INCRE', val)
    // },
    // handleDecre(val) {
    //   this.$store.commit('DECRE', val)
    // },

    // 寫法二:簡寫形式悠瞬,參數(shù)需要從方法名傳過來value(對象)
    ...mapMutations({ handleIncre: 'INCRE', handleDecre: 'DECRE' }),
    // 寫法三:簡寫形式们豌,參數(shù)需要從方法名傳過來value(數(shù)組)  方法名稱必須和vuex里面的方法相同
    // ...mapMutations(['INCRE', 'DECRE']),

    // ==============================================================================================

    // 寫法一
    // handleIncreOdd(val) {
    //   this.$store.dispatch('increOdd', val)
    // },
    // handleIncreWait(val) {
    //   this.$store.dispatch('increWait', val)
    // },

    // 寫法二:
    ...mapActions({ handleIncreOdd: 'increOdd', handleIncreWait: 'increWait' })
    // 寫法三:...mapActions(["handleIncreOdd", 'handleIncreWait']) //方法名稱必須和vuex里面的方法相同
  },
}
</script>

<style>
</style>

stores/index.js

// 引入 vue
import Vue from 'vue'

// 引入vuex
import Vuex from 'vuex'
Vue.use(Vuex)

// 用于存儲(chǔ)數(shù)據(jù)
const state = {
    sum: 0,
    school: 'ans',
    subject: 'web'
}

// 用于操作數(shù)據(jù)(state)
const mutations = {
    INCRE(state, value) {
        state.sum += value
    },

    DECRE(state, value) {
        state.sum -= value
    }
}

// 用于響應(yīng)組件中的動(dòng)作
const actions = {

    increOdd(context, value) {
        if (context.state.sum % 2) {
            context.commit('INCRE', value)
        }
    },

    increWait(context, value) {
        setTimeout(() => {
            context.commit('INCRE', value)
        }, 1000);
    }

}

// 用于 state 中數(shù)據(jù)加工
const getters = {
    bigSum(state) {
        return state.sum * 10
    }
}

// 創(chuàng)建store并導(dǎo)出 store
export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})

Demo2 ==> 計(jì)算小例子

main.js

import Vue from 'vue'
import App from './App'
import router from './router' 
import store from './store' 

Vue.config.productionTip = false


// new Vue({
//   el: '#app',
//   router,
//   components: { App },
//   template: '<App/>'
// })


new Vue({
  el: '#app',
  render:h => h(App),
  router,
  //將創(chuàng)建的共享數(shù)據(jù)對象,掛載在vue實(shí)例中
  //所有的組件浅妆,就可以直接從store中獲取全局的數(shù)據(jù)了
  store
})

store.js

import { subset } from 'semver'
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    //state中存放的就是全局共享的數(shù)據(jù)
    state: {
        //全局count值為0
        count: 0
    },
    mutations: {
        //定義一個(gè)add函數(shù)  第一個(gè)參數(shù)永遠(yuǎn)都是一個(gè)state 代表全局對象
        //加1
        add(state) {
            state.count++
        },
        //加N
        addN(state, step) {
            state.count += step
        },
        //減1
        sub(state) {
            state.count--
        },
        //減N
        subN(state, step) {
            state.count -= step
        }

    },
    actions: {
        //異步操作  context相當(dāng)于new 出來的store的實(shí)體對象
        addAsync(context) {
            setTimeout(() => {
                //修改state中的數(shù)據(jù)必須通過mutations
                context.commit('add')
            }, 2000)
        },
        //等會(huì)2秒異步加N
        addAsyncN(context, step) {
            setTimeout(() => {
                //修改state中的數(shù)據(jù)必須通過mutations
                context.commit('addN', step)
            }, 2000)
        },
        //等待2秒異步減1
        subAsync(context) {
            setTimeout(() => {
                //修改state中的數(shù)據(jù)必須通過mutations
                context.commit('sub')
            }, 2000)
        },
        //等待2秒異步減N
        subAsyncN(context, step) {
            setTimeout(() => {
                //修改state中的數(shù)據(jù)必須通過mutations
                context.commit('subN', step)
            }, 2000)
        }

    },
    getters: {
        //定義函數(shù)
        showNum(state) {
            return '當(dāng)前最新數(shù)據(jù)是[' + state.count + ']'
        }
    }
})

addition.vue 加法組件

<template>
  <div>
    <!-- 加法組件 -->

    <!-- 組件訪問state中數(shù)據(jù)的第一種方式 this.$store.state.全局?jǐn)?shù)據(jù)名稱 -->
    <h3>當(dāng)前最新的count值為:{{ $store.state.count }}</h3>
    <h3>getter包裝的:{{ $store.getters.showNum }}</h3>
    <button @click="btnadd">+1</button>
    <button @click="btnadd2">+3</button>
    <button @click="btnadd3">等待2秒異步+1</button>
    <button @click="btnadd4">等待2秒異步+10</button>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {
    //調(diào)用mutations中提供的一個(gè)函數(shù)
    btnadd() {
      this.$store.commit('add');
    },
    
    btnadd2() {
      this.$store.commit('addN', 3);
    },

    btnadd3() {
      //dispatch函數(shù) 專門用來觸發(fā) action
      this.$store.dispatch('addAsync');
    },

    btnadd4() {
      //dispatch函數(shù) 專門用來觸發(fā) action
      this.$store.dispatch('addAsyncN', 10);
    },
  },
};
</script>

subtraction.vue 減法組件

<template>
  <div>
    <!-- 減法組件 -->
    <h3>當(dāng)前最新的count值為:{{ count }}</h3>
    <h3>getter包裝的:{{ showNum }}</h3>
    <button @click="sub">-1</button>
    <button @click="subN(3)">-3</button>
    <button @click="btnSub3">等待2秒異步-1</button>
    <button @click="btnSub4">等待2秒異步-10</button>
  </div>
</template>

<script>
//組件訪問state中數(shù)據(jù)的第二種方式 先導(dǎo)入
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';

export default {
  data() {
    return {};
  },
  computed: {
    //...展開運(yùn)算符  吧全局里面的那些數(shù)據(jù)映射為當(dāng)前組件的計(jì)算屬性
    //count store中全局共享數(shù)據(jù)名稱   獲取store中的數(shù)據(jù)
    ...mapState(['count']),
    ...mapGetters(['showNum']),
  },
  methods: {
    ...mapMutations(['sub', 'subN']), //吧全局mutations里面的sub函數(shù)映射為當(dāng)前組件的methods
    ...mapActions(['subAsync', 'subAsyncN']),
    // btnSub(){
    //     this.sub();//或者直接加到@click上
    // },
    // btnSub2(){
    //     this.subN(3);//或者直接加到@click上
    // },
    btnSub3() {
      this.subAsync(); //或者直接加到@click上
    },
    btnSub4() {
      this.subAsyncN(10); //或者直接加到@click上
    },
  },
};
</script>

App.vue 跟組件

<template>
  <div>
    <my-add></my-add>
    <p>-------------------------------------------</p>
    <my-sub></my-sub>
  </div>
</template>

<script>
//導(dǎo)入組件
import addition from './components/addition.vue';
import subtraction from './components/subtraction.vue';

export default {
  name: 'App',
  //注冊組件
  components: {
    'my-add': addition,
    'my-sub': subtraction,
  }
}
</script>

<style>
</style>

效果圖如下:

測試.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末望迎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凌外,更是在濱河造成了極大的恐慌辩尊,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件康辑,死亡現(xiàn)場離奇詭異摄欲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)疮薇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門胸墙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人按咒,你說我怎么就攤上這事迟隅。” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵智袭,是天一觀的道長奔缠。 經(jīng)常有香客問我,道長吼野,這世上最難降的妖魔是什么校哎? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮瞳步,結(jié)果婚禮上闷哆,老公的妹妹穿的比我還像新娘。我一直安慰自己谚攒,他們只是感情好阳准,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馏臭,像睡著了一般野蝇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上括儒,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天绕沈,我揣著相機(jī)與錄音,去河邊找鬼帮寻。 笑死乍狐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的固逗。 我是一名探鬼主播浅蚪,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼烫罩!你這毒婦竟也來了惜傲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤贝攒,失蹤者是張志新(化名)和其女友劉穎盗誊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隘弊,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哈踱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梨熙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片开镣。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咽扇,靈堂內(nèi)的尸體忽然破棺而出邪财,到底是詐尸還是另有隱情舅列,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站橄唬,受9級(jí)特大地震影響赊豌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蘑拯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盛霎,春花似錦、人聲如沸耽装。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掉奄。三九已至规个,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間姓建,已是汗流浹背诞仓。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留速兔,地道東北人墅拭。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像涣狗,于是被迫代替她去往敵國和親谍婉。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容