手把手教你使用vuex
vuex什么是vuexVuex 是一个专为 Vue.js 应用程序开发的状态管理模式。可以理解为我们项目中需要共享的一些数据,我们把它集中管理起来的容器。把这些数据称为状态。比如一个用户的用户名,性别,权限级别等等。是否一定要用vuex如果我们不是一个中大型的单页面应用的话,没有那么多的状态需要共享的话就不需要用。对于小项目我们可以只用简单的状态管理:创建:simpleStore.js...
什么是vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
可以理解为我们项目中需要共享的一些数据,我们把它集中管理起来的容器。把这些数据称为状态。比如一个用户的用户名,性别,权限级别等等。
是否一定要用vuex
如果我们不是一个中大型的单页面应用的话,没有那么多的状态需要共享的话就不需要用。对于小项目我们可以只用简单的状态管理:
创建:simpleStore.js
// 简单的状态管理器
const simpleStore = {
state: {
token: '',
userInfo: {
name: '',
sex: 1
}
},
// 设置数据到本地sessionStorage
setStateToStorage (str, obj) {
window.sessionStorage.setItem(str, JSON.stringify(obj))
},
// 清除sessionStorage
removeLocalStorage (str) {
window.sessionStorage.removeItem(str)
},
// 设置用户信息
setUserInfo (obj) {
this.state.userInfo = { ...obj }
this.setStateToStorage('userInfo', this.state.userInfo)
},
// 获取用户信息
getUserInfo () {
return window.sessionStorage.getItem('userInfo')
},
// 清除用户信息
clearUserInfo () {
this.state.userInfo.userName = ''
this.state.userInfo.sex = 1
this.removeLocalStorage('userInfo')
}
}
export default simpleStore
引入并挂载到vue:
import simpleStore from './store/simpleStore'
Vue.prototype.$simpleStore = simpleStore
这毕竟是个简单的状态管理,页面刷新就会导致保存到数据丢失,所以是需要保存到storage才行的。
vuex核心概念
state
所有需要共享的数据都存放在 state 中
定义:
new Vuex.Store({
state: {
token: '',
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
})
在vue组件中使用:
// 直接调用
this.$store.state.token
// 通过计算属性,直接用{{ token }},或者this.token就能调用
computed: {
token () {
return this.$store.state.token
}
}
// 或者调用 mapState
import { mapState } from 'vuex'
computed: {
...mapState({
token: state => state.token
})
// 或者
...mapState([
'token'
])
}
getter
可以对state进行过滤与加工,可以认为是 store 的计算属性
定义:
new Vuex.Store({
getters: {
// state 作为其第一个参数
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// getters 可作为第二个参数
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
},
// 让 getter 返回一个函数,来实现给 getter 传参,对 store 里的数组进行查询时非常有用
getTodoById: state => id => {
return state.todos.find(todo => todo.id === id)
}
// 使用:this.$store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
},
})
在vue组件中使用:
// 直接调用
this.$store.getters.doneTodos
// 通过计算属性,直接用{{ doneTodosCount }},或者this.doneTodosCount就能调用
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
// 或者调用 mapGetters
import { mapGetters } from 'vuex'
computed: {
// getter 属性另取一个名字,使用对象形式
...mapGetters({
doneCount: 'doneTodosCount'
})
// 或者
...mapGetters([
'doneTodos',
'doneTodosCount'
])
}
mutations
在 Vuex 中只能通过提交 mutation 来修改 store 中的状态,且是一个同步的过程
定义:
new Vuex.Store({
mutations: {
// state 作为第一个参数,接收第二个参数为传入的对象
setToken (state, obj) {
const st = state
st.token = obj
}
},
})
在需要多人协作的大型项目中,使用常量替代 Mutation 事件类型:
// 新建 mutation-types.js
export const SET_TOKEN = 'SET_TOKEN' // 设置token
// store.js
import { SET_TOKEN } from './mutation-types'
new Vuex.Store({
mutations: {
// state 作为第一个参数,接收第二个参数为传入的对象
[SET_TOKEN] (state, obj) {
const st = state
st.token = obj
}
},
})
在vue组件中使用:
// 直接调用
this.$store.commit('setToken', obj)
// 在 methods 里使用 mapMutations,就可以 @click="setToken(obj)" 来调用
import { mapMutations } from 'vuex'
methods: {
...mapMutations({
setToken: 'SET_TOKEN'
})
// 或者
...mapMutations([
'setToken',
'SET_TOKEN'
])
}
actions
通过调用 mutation 方法异步的改变 state 状态
定义:
new Vuex.Store({
actions: {
// context 对象作为第一个参数,与 store 实例具有相同方法和属性,但不是 store 实例本身
login (context) {
context.commit('SET_TOKEN')
console.log(context.state)
console.log(context.getters)
}
// es2015 参数结构的方式,接收第二个对象作为参数传入
login ({ commit, state, getters }, obj) {
commit('SET_TOKEN')
}
// 异步操作,例:
login ({ commit }, params) {
const { account, pwd } = params
// 定义一个promise
return new Promise((resolve, reject) => {
// 异步操作
Vue.prototype.$apis.login({ account: account, pwd: pwd }).then(response => {
if (response.code === '000') {
const { data } = response
// 调用mutation
commit('SET_TOKEN', data.token)
setToken(data.token)
// 可以在成功后传出数据
resolve(data.loginStats)
} else {
reject(response.message)
}
}).catch(error => {
reject(error)
})
})
}
// 组合 action,利用async await和dispatch来实现多action的嵌套调用
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
},
})
在vue组件中使用:
// 直接调用
this.$store.dispatch('login', obj)
// 调用 action 中的异步操作,并处理
this.$store.dispatch('login', params).then((val) => {
this.$message.success('登录成功!')
val && this.$router.push('home')
}).catch(err => {
console.log('登录错误: ', err)
})
// 在 methods 里使用 mapActions,就可以 @click="login(obj)" 来调用
import { mapActions } from 'vuex'
methods: {
...mapActions({
login: 'login'
})
// 或者
...mapActions([
'login'
])
}
modules
将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
定义:
// 定义一个 user.js 模块
const user = {
namespaced: false,
state: {
userInfo: {}
},
getters: {
// rootState是根节点状态
getUser (state, getters, rootState) {}
},
mutations: {
setUser (state) {}
},
actions: {
// rootState是根节点状态
getUserInfo ({ state, commit, rootState }) {}
}
}
export default user
// 在store.js中导入
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user' // 导入模块user
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
user
}
})
在vue组件中使用:
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,只有state注册在自己的模块内,调用需要加上模块名。调用的方式:
// state
computed: {
...mapState({
userInfo: state => state.user.userInfo
})
...mapGetters({
getUser: 'getUser'
})
}
// getters
this.$store.getters.getUser
// mutations
this.$store.commit('setUser', obj)
// actions
this.$store.dispatch('getUserInfo', obj)
设置 namespaced: true 使模块具有更高的封装度和复用性。
这时模块内的getter会有第四参数rootGetters,作为访问全局getter:
getters: {
// rootState是根节点状态
getUser (state, getters, rootState, rootGetters) {}
},
actions: {
// rootState是根节点状态
getUserInfo ({ state, commit, rootState, rootGetters }) {}
}
在组件中调用 commit 和 dispatch 时,需要在具体mutation和action前把模块名加上:
// mutations
this.$store.commit('user/setUser', obj)
// actions
this.$store.dispatch('user/getUserInfo', obj)
在设置 namespaced: true 子模块内想要调用全局的 mutation 或者 action 时需要将 { root: true } 作为第三参数传给 dispatch 或 commit:
// mutations
commit('SET_TOKEN', obj, { root: true })
// actions
dispatch('otherModule/getUserInfo', obj, { root: true })
更多推荐
所有评论(0)