vuex的使用
对Vuex的理解
- Vuex是一个专为Vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态
- 你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里,然后将这个对象放在顶层的Vue实例中,让其它组件可以使用,那么,多个组件就可以共享这个对象中的所有变量了,这些变量相当于java中的静态变量
- Vuex给我们提供的最大的便利就是响应式
- 通过原生js中的Protype同样可以实现共享属性,但是却不能实现响应式
- Vuex是一个提供了多个组件间共享状态的插件,这些状态一般是用户登录状态、用户名称、头像、地理位置等
Vuex的基本使用
-
①安装vuex插件
npm install vuex -S
-
②在store文件夹下的index.js文件中使用Vuex插件,类似路由
Vue.use(Vuex)
-
③创建store对象
- 通过
this.$store.state
属性的方式来访问状态 - 通过
this.$store.commit('mutation中的方法')
来修改状态
- 通过
const store = new Vuex.Store({
state: {
//counter:共享变量
counter: 1000
},
mutations: {
increment(state) {
state.counter++
},
changeNum(state, count) {
state.counter += count
}
},
actions: {},
getters: {},
modules: {}
})
[注意事项]:我们通过提交mutations的方式,而非直接改变$store.state.counter
,这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变$store.state.counter
的值
-
④导出store对象
export default store
-
⑤将这个store对象挂载到vue实例中
new Vue({ el: '#app', store, render: h => h(App) })
Vuex核心属性解析
getters
- getters属性相当于计算属性computed,当需要对某个共享变量进行一些封装时,就可以在getters中定义方法
- 默认传入参数state
getters: {
powerCounter(state) {
return state.counter * state.counter
}
- getters属性中定义的方法还可以接受一个额外参数getters,使用这个参数getters就可以调用getters属性中定义的其他方法
cubCounter(state, getters) {
return getters.powerCounter * state.counter
}
- 在使用getters中的方法时,如果有需要传入某个值,这个方法必须返回一个函数,使用这个返回的函数接收传入的值
moreAgeStu(state) {
return function(age) {
return state.students.filter(s => s.age > age)
}
}
- 组件中调用
this.$store.getters.moreAgeStu
mutations
- mutations是Vuex中状态更新的唯一方式:
this.$store.commit('mutation中的方法')
- mutations主要包括两部分内容:
- 字符串的事件类型
- 一个回调函数,该回调函数的第一个参数就是state
- mutations中的定义方法
mutations: {
//increment叫做事件类型,后面部分叫做回调函数
increment(state) {
state.counter++
}
}
- 在通过mutations更新状态时,如果有需要可以传入额外的参数
- 额外传入一个参数,可选择在提交时添加一个参数,这个参数可以是个对象,用于携带更多参数
@click="changeCounter
changeCounter() {
this.$store.commit('changeNum', 5)
}
-
mutations常量类型
- mutations中定义的常量,推荐全部写到一个单独的文件中
- 这些常量统一用大写字母写,需要用到这些常量时再直接导入
//mutations.types.js export const INCREMENT = 'increment'
import { INCREMENT } from './store/mutations.types.js' addition() { this.$store.commit(INCREMENT) }
- 事件类型使用常量时需用中括号[]包裹起来
import * as types from './mutations.types.js' [types.INCREMENT](state) { state.counter++ }
-
响应式为对象添加或删除属性的方式
// 添加属性
Vue.set(state.info, 'address', '洛杉矶')
// 删除属性
Vue.delete(state.info, 'age')
actions
- 通常情况下,Vuex要求我们Mutations中的方法必须是同步方法
- 主要原因是当我们使用devtools时,可以帮助我们捕捉到mutaions的快照
- 但是如果是异步操作,devtools将不能很好的追踪这个操作什么时候会被执行,因此我们引入了actions属性
- actions类似于mutations,但是是用来代替mutations进行异步操作的
- ①在组件中,通过dispatch调用actions中的方法
updateInfo() {
this.$store.dispatch('aUpdateInfo', '我是携带的信息').then(res => console.log(res))
}
- ②将异步代码写在actions的方法中,然后通过commit调用mutations中的方法
- 状态的修改仍需交给mutations
- 将异步代码通过promise封装,使代码更加优雅且便于维护
actions: {
//context在这里相当于store,payload是携带的信息
aUpdateInfo(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updateInfo')
console.log(payload)
resolve('111')
}, 1000)
})
}
}
- ③状态的修改交给mutations中的方法
mutations:{
updateInfo(state) {
state.counter = 20
}
}
modules
- Vue使用单一状态树,那么也意味着状态都会交给Vuex来管理,当应用变得非常复杂时,store对象就有可能变得相当臃肿,为了解决这个问题,Vuex允许我们将store分隔成模块,而每个模块都有自己的state、mutations、actions、actions等
const moduleA = {
state: {
name: '小明'
},
mutations: {},
actions(),
getters: {}
}
const store = new Vuex.Store({
modules: {
a: moduleA
}
})
- ①拿到模块中的state
- a模块会自动被添加到store中的state中
{{$store.state.a.name}}
- ②拿到模块中的mutations
- 模块中的mutations与store中的mutations使用方法无任何区别,不同的是,Vuex会优先从现有的store中寻找mutations,未找到时才会回到模块中寻找
- ③拿到模块中的getters
- 模块中的getters与store中的getters使用方法基本无区别,不同的是,模块中的getter可以接受三个参数,分别是state、getters、rootState,可以获取到store中的state中定的的共享变量
getters: {
fullName(state, getters, rootState) {
return state.name + rootState.counter
}
}
- ④拿到模块中的actions
- 模块中的actions中的context包含rootState、rootGetters