Vuex
基本概念
Vuex 是状态管理工具。集中式存储管理 应用的所有组件的状态,可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面,并将这个变量放在顶层的Vue实例中,让其他组件可以使用,并且实现了响应式。
那么什么状态需要多个组件间共享呢?
例如:用户的登录状态、用户名称、头像、地理位置信息 以及 商品的收藏、购物车中的物品等。
安装
npm install vuex --save
基本结构
├── src
├── index.js 入口js
├── App.vue
├── components
│ ├── HelloWorld.vue
│ └── …
└── store
├── index.js 我们组装模块并导出 store 的地方
├── mutations-types.js 定义类型常量
index.js:
import Vue from 'vue';
import store from './store';
import App from './App.vue';
Vue.config.Vue.config.productionTip = false;
new Vue({
el: '#root',
store, // 挂载之后,每个组件都有一个 $store 对象
render: h => h(App)
});
store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
//安装插件
Vue.use(Vuex)
//创建并导出对象store
export default new Vuex.Store({
state:{
counter : 0
},
mutations:{},
actions:{},
getters:{},
modules:{}
})
每个组件都有一个 $store 对象 , $store 对象有 state 、mutation 、actions 、getters 、modules 属性, 所以各个组件可以通过 ** $store . state . counter ** 来使用此处定义的属性或者方法;通过 this. $state . commit ( mutation 中定义的方法 ) 来修改状态。
【注意】我们通过提交mutation 的方式修改状态,而不是直接更改 $store . state . counter ,这是为了devtools 该工具更明确的追踪状态的变化
getters
getters 相当于计算属性
使用方式一:内部定义的方法默认的参数是 state
getters : {
powerCounter (state) {
return state.counter * state.counter
}
}
<h2>{ $store.getters.powerCounter }</h2>
使用方式二:还能传递另一种参数,就是 getters 本身
getters : {
//筛选年龄大于20的学生
more20stu (state) {
return state.students.filters(s => s.age > 20)
},
//求出年龄大于20的学生的数量
more20stuLength ( state , getters ) {
return getters.more20stu.length
}
}
<h2>{ $store.getters.more20stu }</h2>
<h2>{ $store.getters.more20stuLength }</h2>
使用方式三:getters 本身不能传递其他参数,若想传递其他参数,需要return 一个函数
getters : {
//筛选年龄大于age的学生,age 为传递的参数
moreAgestu (state) {
return function (age) {
return state.students.filters(s => s.age > age)
}
},
}
<!-- 年龄大于18 -->
<h2>{ $store.getters.moreAgestu(18) }</h2>
mutations
更改 store 中state 状态的唯一方式是 : 提交 mutation
mutation 中的方法必须是 同步 方法
mutation 的默认第一个参数是 state
使用方式
使用方式一:不传自定义参数
1、定义mutation:
mutations :
increment ( state ) { // state 是默认参数
state.counter ++
}
}
2、在事件发生的组件中定义函数,在此函数内部提交mutation:
methods : {
addition () {
this.$store.commit ( ' increment ' )
}
}
使用方式二:传一个自定义参数
1、定义mutation:
mutations :
increment ( state , num) {
state.count += num
}
}
2、在事件发生的组件中定义函数,在此函数内部提交mutation:
methods : {
addition ( num ) {
this.$store.commit ( ' increment ' , num )
}
}
使用方式三:传多个自定义参数,需要传递一个 payload 对象
1、定义mutation:
mutations :
increment ( state , payload) {
state.counter += payload.num
}
}
2、在事件发生的组件中定义函数,在此函数内部提交mutation:
methods : {
addition ( num ) {
this.$store.commit ( {
type : ' increment ',
num
} )
}
}
类型常量
在 store 文件下新建一个 mutations-types.js
store/mutations-types.js:
export const INCREMENT = 'increment'
store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
//导入mutations的类型常量
import {
INCREMENT
} from './mutations-type.js'
//安装插件
Vue.use(Vuex)
//创建并导出对象store
export default new Vuex.Store({
state:{
counter : 0
},
mutations:{
// 使用类型常量
[INCREMENT](state){
state.counter ++
}
},
actions:{},
getters:{},
modules:{}
})
App.vue:
<script>
//导入mutations的类型常量
import {
INCREMENT
} from './store/mutations-type.js'
export default {
name: 'App',
data(){},
methods : {
addition ( num ) {
this.$store.commit ( INCREMENT ) // 使用类型常量
}
}
}
</script>
actions
actions 中的默认第一个参数是 context
actions 中的方法必须是 异步 方法
mutation 更改属性,actions 用 commit 提交mutation , 组件里的方法用 dispatch 提交 actions
基本使用方法
store/index.js:
mutations : {
updateInfo (state) {
return state.info.name = 'sea'
}
},
actions : {
aUpdateInfo (context) {
setTimeout( () => {
context.commit('updateInfo') // commit( ' mutations方法 ' )
} , 1000)
}
}
App.vue:
methods : {
update(){
this.$store.dispatch('aUpdateInfo') // dispatch( ' actions方法 ' )
}
}
actions 传递参数
actions 的第二个参数是 payload , 当传递多个参数时,就传递一个 payload 对象
store/index.js:
mutations : {
updateInfo (state) {
return state.info.name = 'sea'
}
},
actions : {
//传递 payload 形参
aUpdateInfo (context , payload) {
setTimeout( () => {
context.commit('updateInfo') // commit( ' mutations方法 ' )
console.log( payload.message )
} , 1000)
}
}
App.vue:
methods : {
update(){
//传递 payload 实参
this.$store.dispatch('aUpdateInfo' , {
message : 'Hello',
fn : function(){}
}) // dispatch( ' actions方法 ' )
}
}
异步 actions 执行成功后,通知组件并执行其他代码
利用 Promise:
store/index.js:
mutations : {
updateInfo (state) {
return state.info.name = 'sea'
}
},
actions : {
//传递 payload 形参
aUpdateInfo (context , payload) {
return new Promise(resolve , reject ){
setTimeout( () => {
context.commit('updateInfo') // commit( ' mutations方法 ' )
console.log( payload );
resolve('执行成功')
} , 1000)
}
}
}
App.vue:
methods : {
update(){
//传递 payload 实参
this.$store
.dispatch('aUpdateInfo' , "我是 payload ")
.then(
res => { console.log (res) }
)
}
}
优化:Vuex的辅助函数mapState,mapGetters, mapActions, mapMutations用法
computed : {
count () {
return this.$store.state.count
}
}
优化为:
import { mapState, mapMutations, mapGetters, mapActions } from 'vuex'
computed : {
...mapState(['count']),
...mapGetters(['evenOrodd'])
}
methods : {
...mapMutations({
increment : 'INCREMENT',
decrement : 'DECREMENT'
})
}