以下内容都是官网上进行学习,https://vuex.vuejs.org/zh/
单向数据流模式:state(驱动应用的数据源) ------》View(以声明方式将state映射到视图) ------》actions(响应在view上的用户输入导致的状态变化) ------》state(更新源数据) -----》、、、再次循环,如下图所示:
但是,当我们的大型项目遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
由此诞生了Vuex, 我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为,通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
sotre(仓库)里面有应用的大部分state(状态),
Vuex 通过 store
选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)
);
new Vue({ router, store, render: h => h(App), }).$mount("#app")
由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
每当 store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
// 创建一个 Counter 组件 const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return store.state.count } } }
mapState
辅助函数
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。
为了解决这个问题,我们可以使用mapState辅助函数帮助我们生成计算属性
computed: mapState([ // 映射 this.count 为 store.state.count 'count' ])
getter: 可以认为是store的计算属性,或者派生出来的状态
就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
mapGetters辅助函数
将store中的getter映射到局部计算属性:
import { mapGetters } from 'vuex' export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }
如果想将一个getter属性领取一个名字,使用对象形式:
...mapGetters({ // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount` doneCount: 'doneTodosCount' })
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
Mutation:
用于更改Vuex的store中的状态的唯一方法是提交mutation.
每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。
这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } })
在组件中调用commit提交改变:
store.commit('increment', 10)
mapMutations:
import { mapMutations } from 'vuex' export default { // ... methods: { ...mapMutations([ 'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')` // `mapMutations` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)` ]), ...mapMutations({ add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')` }) } }
由于Mutation只能是同步函数,所以需要使用Action来实现异步函数
Action:类似于mutation,不同在于:
Action 提交的是mutation,而不是直接变更状态(状态还是在Mutation来变更)。
Action 可以包含任意异步操作
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } })
在组件中使用:
// 以载荷形式分发 store.dispatch('incrementAsync', { amount: 10 }) // 以对象形式分发 store.dispatch({ type: 'incrementAsync', amount: 10 })
mapActions辅助函数:
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` // `mapActions` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` }) } }
总结:
store----》仓库;仓库里面有state-------》状态;状态可以进行重写(派生)------》getter(相当于state的计算属性);
计算属性可以在组件里面通过this.$store.state.属性名使用,或者通过mapGetters辅助函数来使用...mapGetters([属性名1,属性名2....])来使用,如果需要实时监听它的变化,需要放在couputed里面;
组件发生改变需要通过mutation去更新状态(state), 可以通过this.$store.commit('属性名',更新的值)来更新状态,或者通过mapMutations辅助函数来实现:放在methods里面...mapMutations(['方法1','方法名2']),然后在需要状态值改变的地方调用this.方法名1(更新的值)....
由于mutation不能异步更新,所以引入了action,可以通过this.$store.dispatch('属性名',更新的值)来更新状态,或者通过mapActions辅助函数来实现:放在methods里面...mapActions(['方法1','方法名2']),然后在需要状态值改变的地方调用this.方法名1(更新的值)
以上是个人学习笔记,有不对的地方希望各位大佬指教。。。