1

1:状态管理和使用场景(vuex):

vuex所解决的问题与bus类似,它作为Vue的一个插件使用,可以更好的管理和维护整个项目的组件状态。

在实际的业务逻辑中,经常有跨组件共享数据的需要,因此Vuex的设计就是用来更好的管理统一管理组件状
态的。它定义了一系列规范来使用和操作数据,使组件应用更加高效。

1.1: Vuex的基本使用?
    1.1.1: 首先通过NPM进行安装:
         npm  install  --save  vuex
    1.1.2: 在main.jsl文件里,通过Vuer.use()使用Vuex
         import  Vuex  from  'vuex'
         import createrLogger from 'vuex/dist/logger'
        const debug = process.env.NODE_ENV !== 'production'
         Vue.use(Vuex)
     1.1.3: 进行路由配置
          const store = new  Vuex.Store({
                // vuex的配置
                 state: {
                    count: 0,
                    list: [1, 5, 8, 10, 30, 50]
                  },
                  mutations: {
                    increment (state) {
                        state.count++;
                    },
                    decrease (state, n = 1) { // n= n || 1
                        state.count -= n;
                    },
                    ceshiTypeFunc (state, params) {
                            state.count += params.count;
                    }
                  },
                  actions: {
                        increase (context) {
                        context.commit('increase');
                        },
                        asyncIncreasement(xontext) {
                            return new Promise((resolve, reject) => {
                                this.$nextTick(() => {
                                contect.commit('increase');
                                    resolve();
                                })    
                            })
                        }
                  }
                  getters: {
                        filterList: state => {
                            return state.list.filter(item => item< 10);
                        },
                        listCount: (state, getters, rootState) => {
                            // rootState.count 来访问根节点的状态。
                            return  getters.filterList .length;
                        }
                   },
                   plungins: debug ? [crateLogger()] : [];
           });
         仓库store包含了应用的数据(状态)和操作过程。Vuex里面的数据都是响应式的,在任何组件使用同一store的数据
         时候,只要store的数据变化的时候,对应的组件也会立即更新。
         在任何组件中,可以直接通过$store.state.count读取。(模板),直接写在template中会显得会很乱, 可以使用一个
         计算属性来进行显示:
          export default {
                computed: {
                    count() {
                        return this.$store.state.count;
                    },
                    list() {
                        return this.$store.state.list.filter(item => item < 10);
                    },
                    listTwo() {
                        return this.$store.getters.filterList;
                    },
                    listCount() {
                        return this.$store.getters.listCount;
                    }
                }
            }
        1.1.4: 状态值更改?
            在组件中,来自store的数据只能进行读取,不能手动更改, 改变store中的数据的时候唯一途径是使用显示的提交                      mutations(mutations是Vuex的第二个选项, 用来直接修改state里的数据).
            在组件中使用this.$store.commit方法来进行执行mutations中的方法的(例如点击事件)
            methods:  {
                handIncrease () {
                    this.$store.commit('increase');
                 },
                handDecrease () {
                    this.$store.commit('decrease');
                },
                handCeshiFunc () {
                    this.$store.commit({
                        type: 'ceshiTypeFunc ',
                        count: 10
                    });
                },
                handActionIncrease() {
                    this.$store.dispatch('increase');
                },
                handAsyncIncreasement() {
                    this.$store.dispatch('asyncIncreasement ').then(() => {
                        console.log(this.$store.state.count);
                    })
                }
            }
            这样看起来就像Javascript的观察者模式,组件只负责提交一个事件名, Vuex对应的mutations来完成业务逻辑。
            mutation还可以接受第二个参数, 可以是数字、字符串或者对象等。
            注意,mutation里尽量不要使用异步操作数据, 如果异步操作数据,组件在commit后,数据不会立即更新,而且不知                  道什么时候改变。
        1.1.5: 高级用法?
                Vuex还有其他3个选项可以使用: getters、actions、modules.
                 getters: 
                       如果只是想得到小于10的数据, 最容易想到的是通过计算属性进行过滤,这样写是没有问题的,但是如果是
                       其他组件也要使用过滤后的数据的时候,就得吧computed的代码完全复制一份了,而且当需要修改过滤方法                              的时候,每个用到的组件都需要进行修改,这明显不好, 所可以使用getters.
                        注意: getters也可以依赖其他的getters,把getters作为第二个参数。
                  actions:
                        actions与mutation很像,不同的是action里面提交的是mutations,并且可以异步操作业务逻辑。
                        action在组建内通过$store.dispatch触发。
                   modules: 
                        module将store分割到不同的模块,当你的项目足够大的时候,store里的state、getters、mutations、                                    actions会分厂多,放再main.js里面显得不是很友好,使用modules可以将它们写到不同的文件里面,每个                                modules都拥有自己的state、getters、mutations、actions,而且可以多层嵌套。
                       const modulesA = {
                                state: { ... },
                                mutations: { ... },
                                actions: { ... },
                                getters: { ... }
                         }
                        const modulesB = {
                                state: { ... },
                                mutations: { ... },
                                actions: { ... },
                                getters: { ... }
                        }
                        const store = new Vuex.Store({
                                modules: {
                                    a: modulesA,
                                    b: modulesB
                                }
                         })
       1.1.6: 比较?
                 mutations、actions看起来很相似,可能会觉得不知道哪个, 但是Vuex很像是一种与开发者的约定,所以涉及
                 改变数据的,就使用mutations,存在业务逻辑的就用actions.至于将业务逻辑放在你action里还是Vue组件里完                        成的根据实际的业务逻辑拿捏。
1.2: 辅助函数?
            Vuex除了提供我们Store对象之外,还对外提供了一系列的辅助函数,方便我们在代码中使用Vuex,提供了操作store
             的各种属性的一系列的语法糖。
            1.2.1: mapState
                    mapState工具函数会将store中的state映射到局部计算中,为了更好的理解它的实现。

前:(对象)
import { mapState } from 'vuex'
export default {

computed: mapState({
    count: state => state.count,
    // 传入字符串‘count’ 等同于`state => state.count`
    countAlia: 'count', 
    // 想要访问局部状态,就必须借助于一个普通函数,函数中使用`this`获取局部状态。
    countPlusLocalState (state) {
        return state.count + this.localCount;
    }
})

}
经过mapStore函数调用之后的结果:
import {mapState} from 'vuex'
export default {

computed: {
    count() {
        return this.$store.state.count;
    },
    countAlia () {
                return this.$store.state['count'];
            },
          countPlusLocalState () {
                return this.$store.state.count  + this.localCount
            }
}

前:(数组)
import { mapState } from 'vuex'
export default {

computed: mapState([
   'count'
])

}
经过mapStore函数调用之后的结果:
import {mapState} from 'vuex'
export default {

computed: {
    count() {
        return this.$store.state['count'];
    }
}
 

当计算属性名称和状态子树名称对应相等的时候,我们可以向,mapState工具函数中传入一个字符串数组。
computed: mapState({

// 映射this.count 到  this.$store.state.count
'count'

});

                通过例子可以明显看出来mapState函数可以接受一个对象,也可以接受一个数组。
    1.2.2: mapGetters
        mapGetters工具函数将store中的getters映射到局部计算属性属性中,它的功能和mapsState非常类似 

前(数组)
import { mapGetters } from 'vuex'
export default {

computed: {
    ...mapGetters([
        'doneTodoCount',
        'anotherGetter',
        // ...
    ])
}

}
经过mapGetters 函数调用之后的结果:
import { mapGetters } from 'vuex'
export default {

computed:{
    doneTodoCount () {
                return this.$store.getters['doneTodoCount '];
            },
            anotherGetter() {
                this.$store.getters['anotherGetter '];
            }
}

}
前(对象)
computed: mapGetters({

doneCount: 'doneTodosCount'

})
经过mapGetters 函数调用之后的结果:
computed: {
doneCount() {

    return this.$store.getters['doneTodosCount ']

}
}

      1.2.3: mapActions
            mapActions工具函数将store中的dispatch方法映射到组件的methods中,和mapState、mapGetters类似,只不过
            它映射的是地方不是计算属性,而是组件的methods对象上面:


import {mapActions} from 'vuex'
export default {

methods: {
    ...mapActions([
        'increase' // 映射this.increase() 到 this.$store.dispatch('increase');
    ]),
    ...mapActtions([
        add: 'increase' // 映射 this.add() 到 this.$store.dispatch('increase');
     ])
}

}
经过mapActions 函数调用之后的结果:
import { mapActions } from 'vuex'
export default {

methods:{
    increase(...arg) {
        return this.$store.dispatch.apply(this.$store, ['increase'].concat(args))
    },
    add(...arg) {
        return this.$store.dispatch.apply(this.$store, ['increase'].concat(args));
    }
}

}

        1.2.4: mapMutations:
            mapMutations 工具函数会将store中的commit方法映射到组件的methods中,和mapActions的功能几乎一样


import { mapMutatiosn } from 'vuex'
export default {

methods: {
    ...mapMutatiosn ([
        'increase' // 映射this.increase() 到 this.$store.commit('increase');
    ]),
    ...mapMutatiosn ([
        add: 'increase' // 映射 this.add() 到 this.$store.commit('increase');
     ])
}

}
经过mapMutatiosn 函数调用之后的结果:
import { mapMutatiosn } from 'vuex'
export default {

methods:{
    increase(...arg) {
        return this.$store.commit.apply(this.$store, ['increase'].concat(args))
    },
    add(...arg) {
        return this.$store.commit.apply(this.$store, ['increase'].concat(args));
    }
}

}

    1.3: 插件
        Vuex的store接受一个plung 选项,一个Vuex的插件就是一个简单的方法,接受store作为唯一的参数。
        插件的作用通常阿是用来监听每次mustations的变化的,来做一些事情。
        在store的构造函数的最后,我们通过如下代码调用插件。

import devtoolPlungin from './plungins/devtool'

plungins.concat(devtoolPlungin).forEach(plungin => plungin(this))
2: 中央事件总线的使用(vue-bus)

    在本地目录下创建目录vue-bus,在目录vue-bus下插件vue-bus.js文件,此时就给Vue添加了一个属性$bus,并且代理了$emit, $on,$off三个方法, 代理如下

// vue-bus.js
const install = function(Vue) {

const Bus = new Vue({
   methods: {
        emit(event, ...args) {
            this.$emit(event, ...args);
        },
        on(event, ...args) {
            this.$on(event, ...arg);
        },
        off(event, callback) {
            this.$off(event, callback);
        }
    }
});
Vue.prototype.$bus = Bus;

}
export default install;
使用:
// 在main.js 文件中使用

import VueBus from './vue-bus';
Vue,use(VueBus);

// 在view中仙剑一个组件Counter.vue
接收前

<template>
    <div>
            {{number}}
    </div>
    <button @click="handAddRandom">随机增加<button>
</template>
<script>
    export default {
        props: {
            number: {
                type:Number
            }
        },
        methods: {
            handleAddRandom() {
                // 随机回去0-100之间的数值
                const num = Math.floor(Match.random() * 100 + 1);
                this.$bus.emit('add', num);
            }
        }
    }
</script>

接收后

<template>
    <div>
              <Counter :number="number"></Counter> 
    </div>    

·</template>

import Counter from './conter.vue'
<script>
    export default { 
    componrents: {
            Counter
    },
    data: {
        return : {
            number: 0
        }
    },
    methods: {
        handlerAddRandom(num) {
            this.number = num;
        }
    }
    created() {
        this.$bus.on('add', this.handlerAddRandom )
    },
    beforeDestory() {
        this.$bus.off('add', this.handlerAddRandom)
    }
    }
</script>




    
         


歪哥
99 声望5 粉丝

心如花,静若柳,动如风,醉一首诗,醉一阙词