Vuex

146 阅读2分钟

1.Vuex概述

1.1组件之间共享书记的方式

父向子传值 v-bind 子向父传值 v-on 兄弟组件之间共享数据:EventBus

1.2 vuex是什么

Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享

1.3 vuex统一管理状态的好处

  • 能够在vuex中管理共享数据,易于开发和后期维护
  • 能够搞笑地实现组件之间的谁共享,提升开发效率
  • 存储在vuex中的数据都是响应式的,能狗保持数据与页面的同步

1.4 什么样的数据适合存储在vuex中

一般情况喜爱,只有组件之间共享的数据,才有必要存储在vuex中,对于组件中的私有数据,依旧存储在自身的data中。

2 vuex基本使用

  1. 安装vuex依赖包
npm install vuex --save
  1. 导入vux包
import Vuex from 'vux'
Vue.use(Vuex); 
  1. 创建一个store对象
const store = new Vux.Store({

    // state中存放的就是全局共享的数据
    state: {
        count: 0
    },
    
    // 用于修改Store中的数据
    mutation: {}
})
  1. 将store对象挂载到vue实例中
new Vue({
    el: '#app',
    render: h => h(app),
    router,
    store
})

3 vuex的核心概念

3.1 State

State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储

const state = new Vux.Store{{
    state: {
        cousnt: 0
    },
    
    // 不能在mutation中不能执行异步操作
    mutation: {
        add(state) {
            state.count++; 
        },
        addN(state, step) {
            state.count += step;
        }
    },
    
    // 处理异步操作
    actions: {
        addAsync(context) {
            setTimeout(() => {
                // 在Action中,不能直接修改state中的数据
                // 必须通过context.commit()触发mutation
                context.commit('add');
            }, 1000)
        },
        addAsyncN(context, step) {
            setTimeout(() => {
                // 在Action中,不能直接修改state中的数据
                // 必须通过context.commit()触发mutation
                context.commit('addN', step);
            }, 1000)
        }
    }
}}

组件中访问State中数据的第一种方式

this.$state.state.全局数据名称

组件中访问State中的第二个方式

import {mapState} from 'vuex';

通过导入的mapState函数,将当前组件需要的全局数据,映射到当前组件的computed计算属性

computed: {
    ...mapState(['count'])
}

3.2 Mutation

用于变更Store中的数据

  • 只能通过mutation变更Store数据,不可以直接操作Store中的数据
  • 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化

触发mutation的第一种方式-this.$store.commit() 组件中

methods: {
    add() {
        this.$store.commit('add');
    },
    addN() {
        this.$store.commit('add', 3)
    }
}

触发mutation的第二种方式-mapMutation
组件中导入mapMutation

import {mapMutations} from 'vuex';

通过mapMutations函数,将需要的mutations函数,映射为当前组件的methods方法:

methods: {
    ...mapMutations(['add', 'addN'])
}

3.3 Action

Action用于处理异步任务。
提过通过异步操作变更数据,必须通过Action,而不能同时用Mutation,但是Action中还是要通过触发Mutation的方式间接变更数据。 组件中触发action的第一种方式-this.$store.dispatch()

methods: {
    addAsync() {
        this.$store.dispatch('addAsync')
    },
    addAsyncN() {
        this.$store.dispatch('addAsyncN', 3);
    }
}

组件中触发action的第二种方式-mapActions

import {mapActions} fron 'vuex';

……
methods: {
    ...mapActions(['addAsync', 'addAsyncN'])
}

3.4 Getter

Getter用于对Store中的函数进行加工处理形成新的数据

  • Getter可以对Store中已有的数据加工处理后形成新的数据,类似Vue的计算属性
  • Store中的数据发狠恶搞变化,Getter的数据也会跟着变化
const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        showNum: state => {
            return `当前最新的数据量是【${state.count}】`
        }
    }
})

使用getter的第一种方式-this.$store.getters.名称
使用getter的第二种方式-mapGetters

import {mapGetters} from 'vuex'

……
computed: {
    ...mapGetters(['showNum'])
}

4 手写vuex

 let Vue;
 const Store {
     constructor(options = {}) {
         this.state = options.state;
         
         // Vuex的核心,实现数据响应式
         this.s = new Vue({
             data() {
                 return {state: options.state}
             }
         });
         // state
         get state() {
             return this.s.state;
         }
         
         // getters 对象
         let getters = options.getters;
         this.getters = {}; 
         Object.keys(getters).forEach((getterName) => {
             Object.defineProperty(this.getters, getterName,
                 {
                     get: () => {
                         return getters[getterName](this.state)
                     }
                 }
             )
         });
         
         let mutations = options.mutations;
         this.mutations = {}
         Object.keys(mutations).forEach(mutationName => {
             this.mutations[mutationName] = (payload) => {
                 mutations[mutationName](this.state, payload)
             }
         });
         
         commit(mutationName, payload) {
             this.mutations[mutationName](payload);
         }
         
         let actions = options.action;
         this.actions = {};
         Object.keys(actions).forEach(actionName => {
             this.actions[actionName] = (payload) => {
                 actions[actionName](this, payload);
             }
         });
         dispatch(actionName, paylod) {
             this.actions[actionName](paylod);
         }
         
     }
 }
 const install = function(_vue) {
     Vue = _Vue;
     
     // 混入生命周期
     Vue.mixin({
         // new Vue的时候,和app渲染的时候都会执行,工作还行两次
         beforeCreate() {
             if(this.$option && this.$option.$store) {
                 this.$store = this.$options.store;
             }
             else {
                 this.$store = this.$parent && this.$parent.$store;
             }
             // 为什么不挂在Vue.prototype
             // 1. new Vue()每个实例都会带store
             // 2. 不会污染原型
             // 3. 单独创建的实例,没有父亲,没有store
         }
     })
     console.log('install')
 }
 export default {
     install,
     Store
 }