Vuex的基本概念及使用

Vuex:

    本文只是对vuex官方文档的一点自己方式的"翻译",记录了vuex的一些基本概念及简单的使用。

Vuex:
    --Vuex是什么?
        Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
        以上是vue官方很官方的解释简单的说:vuex是一个数据仓库,管理状态(数据)。
    --什么时候使用Vuex:
        Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
        如果您不打算开发大型单页应用(比如你的项目只有几页(组件)),那么使用 Vuex 可能是繁琐冗余的。
        确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。
        但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
        还是很官方...简单的说就是必须使用:不使用项目会变得特别复杂或者做不下去了 的时候就是vuex出场的时候了。
    1:Vuex的简单使用:
        --1.1:安装vuex:
            npm install vuex --save
        --1.2:引入vuex:
            在src下新建store文件夹,新建store.js文件
            import Vue from 'vue'
            import Vuex from 'vuex'
            Vue.use(Vuex)
        --3:创建一个store数据仓库,并实例化vuex,export default 实例:
            const state={
                count:0
            }
            export default new Vuex.Store({
                store
            })
        --4:在需要使用的page,引入store/store:
            import store from '@/store/store'
            export default {
                name,
                data(){},
                store
            }
       --5:根据项目需求,读取状态/改变状态/操作状态
    2:State:
        Vuex使用单一状态树———用一个对象就包含了全部的应用层级状态。至此它便作为一个唯一数据源而存在。
        这也意味着每个应用将仅仅包含一个store实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
        --如何在vue组件中获得vuex状态?
            方式一:
                在vue组件中引入store后通过:$store.state.name读取状态
            方式二:
                通过计算属性方式,简化读取:
                    comuted:{
                        count(){
                            return this.$store.state.count;
                        }
                    }
            方式三:
                通过mapState辅助函数:
                当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题我们可以使用mapState辅助函数帮助我们生成计算属性;
                1:首先在需要使用的组件中引入:
                    import { mapState} from 'vuex'
                2:在组件计算属性中使用:
                    computed:mapState({
                        //使用箭头函数简化代码
                        count:state=>state.count
                        //传字符串参数:'count'等同于箭头函数:state=>state.count
                        countA:'count',
                        //如果要使用this获取局部状态,那么必须使用常规函数
                        countP(state){
                            return state.count + this.num
                        }
                    })
            方式四:
                通过mapState传入数组的形式获取状态:
                computed:mapState(['count'])
                
                
    3:Mutation:
        更改vuex的store中的状态的唯一方法是提交mutation。
        vuex中的mutation非常类似于事件:每个mutation都由一个字符串的事件类型(type)和一个回调函数(handler)。
        这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数。
        需要注意的是:
            我们不能直接调用一个mutation handler。这个选项更像是事件注册:
            当触发一个类型为increment的mutation时,调用此函数。要唤醒一个mutation handler需要以相应的type调用store.commit()方法:
            store.commit('increment')。
        实例:
            const store = new Vuex.Store({
              state: {
                count: 1
              },
              mutations: {
                increment (state) {
                  // 变更状态
                  state.count++
                }
              }
            })
            在需要调用的页面:@click="$store.commit('increment')"
        --传递参数(提交载荷payload):
            我们可以向store.commit传入额外的参数,即mutation的载荷(payload):
            注1:mutations内的回调函数第一个参数为state。
            注2:大多数情况下,载荷应该为一个对象,这样可以包含多个字段并且记录mutation会更易读。
            mutations: {
              increment (state, n) {
                state.count += n
              }
            }
            $state.commit('incerment',66)
            传递一个对象作为参数:
            mutations:{
                increment(state,obj){
                    state.count=obj.num
                }
            }
            $state.commit('increment',{
                num:10
            })
        
        --对象风格的mutation提交方式:
            直接使用包含type属性的对象方式来提交,type值为mutations内定义的回调函数名:
            $store.commit({
                type:'incerment',
                num:66
            })
            
        --Mutation必须为同步函数,不可以是回调函数
            在使用mutation时有一条重要的原则:
                mutation必须为同步函数,不可以是回调函数。因为:
                首先看一个简单的例子:
                    mutations: {
                      someMutation (state) {
                        api.callAsyncMethod(() => {
                          state.count++
                        })
                      }
                    }
                每一条mutation被记录,都需要捕捉到前一状态和后一状态的快照。然而在上面的例子中mutation中的异步函数中的回调是不可能完成的,因为当mutation触发的时候,回调函数还没有被调用,vue不知道什么时候回调函数实际上被调用。
            注:实际上任何在回调函数中进行的状态的改变都是不可追踪的。
        
        --在组件中提交mutation:
            方式一:
                上面已经说过了这种方式:在组件中直接使用this.$store.commit('xxx')提交mutation。
            方式二:
                如果我们不想在template中写过多的行为(js),那么我们可以在methods中定义一个方法在方法中提交mutation:
                methods:{
                    submit(){
                        this.$store.commit('xxx')
                    }
                }
                这样我们只需要在template中调用定义好的method即可,更加易读。这种方式实际上只是将template内的js换到了methods内,还是比较麻烦。
            方式三:
                我们可以使用mapMutations辅助函数将组件中的methods映射为store.commit调用。
                注:mapMutations需要先import:
                    import { mapMutations } from 'vuex'
                export default{
                    methods:{
                        ...mapMutations({
                            add:'increment' //将this.add()映射为this.$store.commit('increment')
                        })
                        
                        ...mapMutations([
                            'increment' //将this.increment()映射为this.$store.commit('increment')
                        ])
                    }
                }
                --通过mapMutations方式怎么传参呢?
                    参数并非是在mapMutations内部传递,而是在调用的地方传递参数,mapMutations只是进行映射而已。
                    <input type="button" value="+" @click="add(10)" />
    
    4:Action:
        Action与Mutation很相似,都是用来修改state内的状态的。
        在上面Mutation内我们提到了Mutation的一个很重要的原则:Mutation必须为同步操作。
        Action提交的是mutation,与Mutation不同的是:Action可以包含任意异部操作
        首先注册一个action:
        const actions={
            incerment(context){
                context.commit('increment')
            }
        }
        Action函数接受一个与store实例具有相同属性和方法的context对象。
        因此可以调用context.commit提交一个mutation,或者通过context.state和context.getter来获取state和getters。
        同样的在局部组建中import {mapActions} from 'vuex'
        然后在methods内通过mapActions映射:
        methods:{
            ...mapActions(['incerment'])
        }
        在template内通过事件触发:例如:@click="incerment"即可。
        
        如果仅仅是这样那么action与mutation功能上没有任何区别,反而比mutation更加麻烦。action的作用在于执行异步操作:
        const actions={
            incermentAsync(context){
                setTimeout(()=>{
                    context.commit('increment')
                },5000)
            }
        }
                
    5:Getter:
        Getter相当于vue中的compute的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生改变才会被重新计算。
        Getter可以用于监听state中的值的变化,反悔计算后的结果。
        --通过属性访问:
            Getter会暴露为store.getters对象,可以以属性的形式访问这些值:
            store.getters.name
        --通过方法访问:
            通过让getter返回一个函数来实现给getter传参。这在对store里的数组进行查询时非常有用。
            getters:{
                getArrId(store,id){
                    return (id)=>{
                        return state.arrdata[2]
                    }
                }
            }
            注意:getter在通过方法访问时每次都会去进行调用,而不会缓存结果。
        --mapGetter辅助函数:
            mapGetter辅助函数仅仅是将store中的getter映射到局部的计算属性。
            computeds:{
                ...mapGetter(['getarrdata'])
            }
            如果想将getter属性取另外一个name,使用对象形式:
            computeds:{
                ...mapGetter({
                    getdata:'getarrdata'
                })
            }
            
    6:Module:
        由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
        为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
        const moduleA = {
          state: { ... },
          mutations: { ... },
          actions: { ... },
          getters: { ... }
        }

        const moduleB = {
          state: { ... },
          mutations: { ... },
          actions: { ... }
        }

        const store = new Vuex.Store({
          modules: {
            a: moduleA,
            b: moduleB
          }
        })

        store.state.a // -> moduleA 的状态
        store.state.b // -> moduleB 的状态
          

猜你喜欢

转载自blog.csdn.net/qq_41558265/article/details/90700934