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
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>
效果圖如下: