Vuex主要解决的问题
我们经常需要一个状态,数据需要在多个组件之间互用,比如昵称,头像
vuex官方文档
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
1、Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2、你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
在运用之前需要安装VueX依赖
首先在state文件夹下面创建一个入口文件(index.js)和mutation.js和action.js
Vuex的核心就是仓库store,以下定义的是入口文件index.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import actions from './action'
Vue.use(Vuex)
const state ={
username:'dean',
cartCount:3
}
export default new Vuex.Store({
state,
mutations,
actions
})
这里定义的store状态是一个username和cartCount,定义的初始值分别是dean和3
在main.js里面注册store选项,则该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问。
import store from './store'//这里的./store是网我的文件路径
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
Mutation
在main.js里面注册store选项,则该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问。
Mutation.js
export default{
saveUserName(state,username){
state.username=username;
},
saveCartCount(state,count){
state.cartCount=count;
},
addNewState(state, payload) { //添加新的属性到state
this.replaceState({...state, newProp: payload})
}
}
这里是在commit时提交额外的参数,这里我传了额外的值到username和count中
addNewState是添加一个新的状态
获取状态
注意这个如果涉及到要在store里面会被改变的状态,一定要写在 computed属性里面,不然不能及时反馈到视图上
computed: {
newProp() {
return this.$store.state.newProp || '还没添加新值';
},
username() { //
return this.$store.state.username;
},
cartCount() {
return this.$store.state.cartCount;
}
},
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,但需要先在组件中导入
import { mapState } from 'vuex'
然后在computed中写入
computed: {
/**
方法一
*/
// newProp() {
// return this.$store.state.newProp || '还没添加新值';
// },
// username() {
// return this.$store.state.username;
// },
// cartCount() {
// return this.$store.state.cartCount;
// }
/**
方法二
*/
...mapState(['newProp', 'username', 'cartCount'])
},
然后在页面中引用
<p>添加的新值:{{newProp}}</p>
<p>用户名:{{username}}</p>
<p>数量:{{cartCount}}</p>
<input type="text" v-model="addMsg">
<div><button @click="addNewProp">添加新值</button></div>
实际效果:由于还未添加newProp属性所以在store还未产生这个属性
Action
Action 提交的是 mutation,而不是直接变更状态
Action 可以包含任意异步操作。 前面说过mutation只能包含同步事务,所以在处理异步事务就需要Action,通过Action控制了异步这一过程,之后再去调用mutation里面的方法来改变状态
Action.js
export default{
saveUserName(context,username){
context.commit('saveUserName',username);
},
saveCartCount(context,count){
context.commit('saveCartCount',count);
},
addNewState(context,msg){
context.commit('addNewState',msg);
}
}
然后在方法中定义事件触发分发:
methods: {
addNewProp() {
this.$store.dispatch('addNewState', this.addMsg)
this.$store.dispatch('saveUserName', 'winnie')
this.$store.dispatch('saveCartCount', '22')
}
}
这里同样有辅助函数mapActions ,由于这边还需要传入参数所以显得也不是很简洁
首先还是需要导入mapActions
import {mapActions} from 'vuex'
methods: {
/**方法二*/
...mapActions(['addNewState', 'saveUserName', 'saveCartCount']),
addNewProp() {
/**方法二 */
this.addNewState(this.addMsg);
this.saveUserName('winnie');
this.saveCartCount('22');
/**
方法一
*/
// this.$store.dispatch('addNewState', this.addMsg)
// this.$store.dispatch('saveUserName', 'winnie')
// this.$store.dispatch('saveCartCount', '22')
}
}
实际效果