一 、安装并使用Vuex
- 一般新建vue项目的时候都会让你选择是否安装vuex, 如果没有选择安装的话,通过下面的代码进行安装:
npm install vuex --save or yarn add vuex
- 在 src 目录下新建 store 文件夹, 在 store 文件下新建 index.js
import Vue form 'vue'
import Vuex form 'vuex'
Vue.use(Vuex);
// 创建vuex实例
const store = new Vuex.Store({
state:{},
getters:{},
mutations:{},
actions:{},
modules: {}
})
- 然后再main.js文件中引入Vuex
import store from './store';
new Vue({
store, // store: store
render: h => h(App)
}).$mount('#app')
二 、Vuex的核心属性
state
state:初始化数据,相当于
Vue
中的data
属性
使用方法:如果只用到一个state
状态
this.$store.state.msg // 访问总仓库
this.$store.state.a.msg // 访问子仓库
使用多个state
状态:使用mapState
辅助函数, 利用对象展开运算符将state
混入computed
对象中,然后直接用this.a
访问就行,以下所有通过辅助函数映射到组件的,都可以这样访问
import {mapState} from 'vuex'
export default{
computed:{
...mapState(['a','b'])
}
}
getters
getters:计算属性,相当于
Vue
中的computed
属性,getter
接收两个参数,第一个是state
,第二个是getters
(可以用来访问其他getter
)
const store = new Vuex.Store({
state: {
price: 10,
count: 2
},
getters: {
total: state => {
return state.price * state.count
},
discountTotal: (state, getters) => {
return state.price * getters.total
}
},
});
使用方法:如果只用到一个getters
状态
this.$store.getters.total// 访问总仓库
this.$store.getters.a.total// 访问子仓库
使用多个getters
状态:使用mapGetters
辅助函数, 利用对象展开运算符将getters
混入computed
对象
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(['total','discountTotal'])
}
}
可以通过给getters
传参来获取满足要求的数据,然后在组件中this.$store.getters.getTodoById(2)
这样来访问
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
getTodoById: (state) => (id) =>{
return state.todos.find(todo => todo.id === id)
}
},
});
mutations
mutations: 用来修改
state
中的状态,在开启严格模式下, 只能通过提交一个mutation
来修改state
状态,否则会报错。mutation
可以接收state
作为第一个参数,也可以接收第二个参数作为调用时传来的参数。mutation
中只能写同步操作, 异步操作要放在action
中。
const store = new Vuex.Store({
// 开启严格模式 防止直接对vuex做修改 只能通过mutation进行修改 this.$store.state.a = 'hello' 会报错
// 严格模式会深度监测状态树来检测不合规的状态变 化,造成不必要的性能损失,正式环境不要开启严格模式
strict: true,
state: {
userName: ''
},
mutations: {
login(state, name){
state.userName = name
}
}
})
使用方法:通过store
实例访问(适用于mutation的方法较少时)
this.$store.commit('login', 'admin')
使用多个mutation中的方法时:使用mapMutations
辅助函数, 利用展开运算符将mutation
混入methods
中
import {mapMutations} from 'vuex'
export default {
methods: {
...mapMutations(['login', 'logout'])
},
created(){
this.login('admin')
this.logout()
}
}
actions
actions:
actions
可以包含任意异步操作,但不能直接修改state
状态,只能通过commit
一个mutation
来修改状态。actions接收context为第一个参数,接收第二个为调用时传入的参数。
假如现在我们把发起登录的请求放到actions
里面
const store = new Vuex.Store({
state: {
setUserInfo: ''
},
mutations: {
setUserInfo(state, info){
state.setUserInfo = info
}
},
actions: {
// context 包含以下参数: state, rootState, commit, dispatch, getters, rootGetters
login(context,params){
login(params).then(res => {
context.commit('setUserName', res.data)
})
}
// 使用es6解构赋值 推荐这种
login({commit},params){
login(params).then(({data})=> {
commit('setUserName', data)
})
}
}
})
使用方法:通过store
访问(适用于action的方法使用较少时)
this.$store.dispatch('login', this.loginForm)
使用多个actions方法时:使用mapActions
辅助函数,使用展开运算符将action
混入methods
import {mapActions} from 'vuex'
export default {
methods: {
...mapActions(['login'])
},
created(){
this.login(this.loginForm)
}
}
modules
modules:当我们的项目很大时,为了方便维护,就不可能将所有状态维护在总仓库。
vuex
允许我们可以根据业务需求将仓库进行模块化(拆分成子仓库),此时modules
就用上了。子仓库和总仓库不同的是子仓库有namespaced
属性。
假如我们有一个购物车模块和我的信息模块,而我们没有开启命名空间,cart
和mine
的actions
中都有一个getList方法,我们通过的访问方式调用getList方法会触发两个getList,这显然不是我们想要的。
打个比喻,比如一个班级里有两个叫小明的(一个村东头,一个村西头 ),老师让小明站起来回答问题,结果两个小明都站起来了,而namespaced
的作用就相当于老师明确让村哪头的小明回答问题。
// 总仓库
import cart from './cart.js'
import mine from './mine.js'
const store = new Vuex.store({
modules: { // 注册模块
cart,
mine
}
})
// 子仓库 在store目录下新建cart.js文件 mine同cart
export default{
namespaced: true // 开启命名空间,开启后组件访问子仓库的状态和方法将不一样,
state:'' // 其他属性都同总仓库一样
...
}
因为总仓库没有命名空间,所以访问总仓库方式不变,以下变动只针对于子仓库
开启命名空间后:不使用辅助函数访问
this.$store.state.user.userName // 访问state方式不变
this.$store.getters['user/wellcom'] // 访问getters
this.$store.commit['user/setInfo'] // 访问mutations
this.$store.dispatch['user/login'] // 访问actions
使用辅助函数访问,变更为以下方式:
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
export default {
computed: {
// 访问user模块下state和getters
...mapState('user', ['userInfo']), // this.userInfo
...mapGetters('user', ['userName'])
// 也可以使用对象方式
...mapState({myInfo: ['user/userInfo']}), // this.myInfo
...mapGetters({myName: ['user/userName']})
},
methods: {
// 访问user模块下的mutations和actions
...mapMutations(['user/setInfo']),// this['user/setInfo']()
...mapActions(['user/login']) // this['user/login']()
}
}
如果不熟悉对象使用[]
和.
获取属性的区别,可以看看这篇文章JavaScript对象属性带引号和不带引号的区别
推荐使用辅助函数的方式访问仓库,因为使用的越多,这种方式少写代码的优点就体现出来了。