zoukankan      html  css  js  c++  java
  • vuex笔记

    本文基本上是官方教程的盗版,用通俗易懂的文字讲解Vuex,也对原文内容有删减。

    如果你对以上声明不介意,那么就可以继续看本文,希望对你有所帮助。

    学习一个新技术,必须要清楚两个W,"What && Why"。

    "XX 是什么?","为什么要使用 XX ,或者说 XX 有什么好处",最后才是"XX 怎么使用"。

    Vuex是什么?

    Vuex 类似 Redux 的状态管理器,用来管理Vue的所有组件状态。

    为什么使用Vuex?

    当你打算开发大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。

    遇到以上情况时候,你就应该考虑使用Vuex了,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。

    下面讲解如何使用Vuex。

    最简单的Vuex示例

    本文就不涉及如何安装Vuex,直接通过代码讲解。

    import Vue from 'vue';
    import Vuex form 'vuex';
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            increment (state) {
                state.count++
            }
        }
    })

    以上就是一个最简单的Vuex,每一个Vuex应用就是一个store,在store中包含组件中的共享状态state和改变状态的方法(暂且称作方法)mutations

    需要注意的是只能通过mutations改变store的state的状态,不能通过store.state.count = 5;直接更改,state相当于对外的只读属性。

    使用store.commit方法触发mutations改变state:

    store.commit('increment');
    
    console.log(store.state.count)  // 1

    一个简简单单的Vuex应用就实现了。

    在Vue组件使用Vuex

    如果希望Vuex状态更新,相应的Vue组件也得到更新,最简单的方法就是在Vue的computed(计算属性)获取state

    // Counter 组件
    const Counter = {
        template: `<div>{{ count }}</div>`,
        computed: {
            count () {
                return store.state.count;
            }
        }
    }

    上面的例子是直接操作全局状态store.state.count,那么每个使用该Vuex的组件都要引入。为了解决这个,Vuex通过store选项,提供了一种机制将状态从根组件注入到每一个子组件中。

    // 根组件
    import Vue from 'vue';
    import Vuex form 'vuex';
    
    Vue.use(Vuex);
    const app = new Vue({
        el: '#app',
        store,
        components: {
            Counter
        },
        template: `
            <div class="app">
                <counter></counter>
            </div>
        `
    })

    通过这种注入机制,就能在子组件Counter通过this.$store访问:

    // Counter 组件
    const Counter = {
        template: `<div>{{ count }}</div>`,
        computed: {
            count () {
                return this.$store.state.count
            }
        }
    }

    mapState函数

    computed: {
        count () {
            return this.$store.state.count
        }
    }

    这样通过count计算属性获取同名state.count属性,是不是显得太重复了,我们可以使用mapState函数简化这个过程。

    import { mapState } from 'vuex';
    
    export default {
        computed: mapState ({
            count: state => state.count,
            countAlias: 'count',    // 别名 `count` 等价于 state => state.count
        })
    }

    还有更简单的使用方法:

    computed: mapState([
      // 映射 this.count 为 store.state.count
      'count'
    ])

    Getters对象

    如果我们需要对state对象进行做处理计算,如下:

    computed: {
        doneTodosCount () {
            return this.$store.state.todos.filter(todo => todo.done).length
        }
    }

    如果多个组件都要进行这样的处理,那么就要在多个组件中复制该函数。这样是很没有效率的事情,当这个处理过程更改了,还有在多个组件中进行同样的更改,这就更加不易于维护。

    Vuex中getters对象,可以方便我们在store中做集中的处理。Getters接受state作为第一个参数:

    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)
        }
      }
    })

    在Vue中通过store.getters对象调用。

    computed: {
      doneTodos () {
        return this.$store.getters.doneTodos
      }
    }

    Getter也可以接受其他getters作为第二个参数:

    getters: {
      doneTodos: state => {
          return state.todos.filter(todo => todo.done)
      },
      doneTodosCount: (state, getters) => {
        return getters.doneTodos.length
      }
    }

    mapGetters辅助函数

    mapState类似,都能达到简化代码的效果。mapGetters辅助函数仅仅是将store中的getters映射到局部计算属性:

    import { mapGetters } from 'vuex'
    
    export default {
      // ...
      computed: {
        // 使用对象展开运算符将 getters 混入 computed 对象中
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
      }
    }

    上面也可以写作:

    computed: mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])

    所以在Vue的computed计算属性中会存在两种辅助函数:

    import { mapState, mapGetters } form 'vuex';
    
    export default {
        // ...
        computed: {
            mapState({ ... }),
            mapGetter({ ... })
        }
    }

    Mutations

    之前也说过了,更改Vuex的store中的状态的唯一方法就是mutations

    每一个mutation都有一个事件类型type和一个回调函数handler

    const store = new Vuex.Store({
      state: {
        count: 1
      },
      mutations: {
        increment (state) {
          // 变更状态
          state.count++
        }
      }
    })

    调用mutation,需要通过store.commit方法调用mutation type

    store.commit('increment')

    Payload 提交载荷

    也可以向store.commit传入第二参数,也就是mutation的payload:

    mutaion: {
        increment (state, n) {
            state.count += n;
        }
    }
    
    store.commit('increment', 10);

    单单传入一个n,可能并不能满足我们的业务需要,这时候我们可以选择传入一个payload对象:

    mutation: {
        increment (state, payload) {
            state.totalPrice += payload.price + payload.count;
        }
    }
    
    store.commit({
        type: 'increment',
        price: 10,
        count: 8
    })

    mapMutations函数

    不例外,mutations也有映射函数mapMutations,帮助我们简化代码,使用mapMutations辅助函数将组件中的methods映射为store.commit调用。

    import { mapMutations } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapMutations([
          'increment' // 映射 this.increment() 为 this.$store.commit('increment')
        ]),
        ...mapMutations({
          add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
        })
      }
    }

    注 Mutations必须是同步函数。

    如果我们需要异步操作,Mutations就不能满足我们需求了,这时候我们就需要Actions了。

  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/shuiche/p/7411859.html
Copyright © 2011-2022 走看看