vuex 理解
vuex 是什么
1) github 站点: https://github.com/vuejs/vuex
2) 在线文档: https://vuex.vuejs.org/zh-cn/
3) 简单来说: 对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
状态自管理应用
1) state: 驱动应用的数据源
2) view: 以声明方式将 state 映射到视图
3) actions: 响应在 view 上的用户输入导致的状态变化(包含 n 个更新状态的方法)
多组件共享状态的问题
1) 多个视图依赖于同一状态
2) 来自不同视图的行为需要变更同一状态
3) 以前的解决办法
a. 将数据以及操作数据的行为都定义在父组件
b. 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
4) vuex 就是用来解决这个问题的
vuex 核心概念和 API
state
1) vuex 管理的状态对象
2) 它应该是唯一的
const state = {
xxx: initValue
}
mutations
1) 包含多个直接更新 state 的方法(回调函数)的对象
2) 谁来触发: action 中的 commit('mutation 名称')
3) 只能包含同步的代码, 不能写异步代码
const mutations = {
yyy (state, {data1})
{
// 更新 state 的某个属性
}
}
actions
1) 包含多个事件回调函数的对象
2) 通过执行: commit()来触发 mutation 的调用, 间接更新 state
3) 谁来触发: 组件中: $store.dispatch('action 名称', data1) // 'zzz'
4) 可以包含异步代码(定时器, ajax)
const actions = {
zzz ({commit, state}, data1){
commit(
'yyy', {data1}
)
}
}
getters
1) 包含多个计算属性(get)的对象
2) 谁来读取: 组件中: $store.getters.xxx
const getters = {
mmm (state) {
return ...
}
}
modules
1) 包含多个 module
2) 一个 module 是一个 store 的配置对象
3) 与一个组件(包含有共享数据)对应
向外暴露 store 对象
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
组件中
import {mapState, mapGetters, mapActions} from 'vuex'
export default {
computed: {
...mapState(['xxx']),
...mapGetters(['mmm']),
}
methods: mapActions(['zzz'])
}
{{xxx}} {{mmm}} @click="zzz(data)"
映射 store
import store from './store'
new Vue({
store
})
store 对象
1) 所有用 vuex 管理的组件中都多了一个属性$store, 它就是一个 store 对象
2) 属性: state: 注册的 state 对象 getters: 注册的 getters 对象
3) 方法: dispatch(actionName, data): 分发调用 action
实际案例
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
/*state 对象 类似于 data */
const state = {
count: 0
// 初始化状态数据
}
/*
mutations 对象包含个方法:
能直接更新 state 一个方法就是一个 mutation mutation
只能包含更新 state 的同步代码, 也不会有逻辑
mutation 由 action 触发调用: commit('mutationName')
*/
const mutations = {
INCREMENT(state) {
state.count++
},
DECREMENT(state) {
// ctrl + shift + x
state.count--
}
}
/*
actions 对象 包含个方法: 触发 mutation 调用,
间接更新 state 一个方法就是一个 action action
中可以有逻辑代码和异步代码 action 由组件来触发调用:
this.$store.dispatch('actionName')
*/
const actions = {
increment({
commit
}) {
commit('INCREMENT')
},
decrement({
commit
}) {
commit('DECREMENT')
},
incrementIfOdd({
commit,
state
}) {
if (state.count % 2 === 1) {
commit('INCREMENT')
}
},
incrementAsync({
commit
}) {
setTimeout(() => {
commit('INCREMENT')
}, 1000)
}
}
/*getters 对象 包含多个 get 计算计算属性方法 */
const getters = {
oddOrEven(state) {
return state.count % 2 === 0 ? '偶数' : '奇数'
},
count(state) {
return state.count
}
}
// 向外暴露 store 实例对象
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
main.js
import Vue from 'vue'
import app from './app.vue'
import store from './store'
// 创建 vue 配置路由器
new Vue({
el: '#app',
store,
render: h => h(app)
})
app.vue(未优化前)
<template>
<div>
<p>clicked: {{$store.state.count}} times, count is {{oddOrEven}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">increment if odd</button>
<button @click="incrementAsync">increment async</button>
</div>
</template> <script>
export default {
computed: {
oddOrEven() {
return this.$store.getters.oddOrEven;
}
},
methods: {
increment() {
this.$store.dispatch("increment");
},
decrement() {
this.$store.dispatch("decrement");
},
incrementIfOdd() {
this.$store.dispatch("incrementIfOdd");
},
incrementAsync() {
this.$store.dispatch("incrementAsync");
}
}
};
</script> <style>
</style>
app2.vue(优化后)
<template>
<div>
<p>clicked: {{count}} times, count is {{oddOrEven2}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">increment if odd</button>
<button @click="incrementAsync">increment async</button>
</div>
</template> <script>
import { mapGetters, mapActions } from "vuex";
export default {
computed: mapGetters({
// 名称不一样
oddOrEven2: "oddOrEven",
count: "count"
}),
methods: mapActions([
"increment",
"decrement",
"incrementIfOdd",
"incrementAsync"
]) // 名称一样
};
</script>
<style>
</style>