Vue2手捏Vuex插件

本文详细介绍了如何在Vue应用中使用Vuex进行状态管理,包括如何存储初始状态、修改数据(mutations和actions)、以及使用getters计算属性。通过实例展示了如何在Store、index.js和App.vue中实现这些功能。
摘要由CSDN通过智能技术生成

一、展示数据(state)

1. plugins/Vuex.js:

let Vue;

class Store {
    constructor(options) {
        // 1. 保存数据 通过 vue 中的 data 是响应式 
        this._vm = new Vue({
            data: {
                $$state: options.state
            },
        })
    }
    // 代理(设置访问器的方式来限制访问)
    get state() {
        return this._vm._data.$$state;
    }
}


// 定义一个install方法
function install(_Vue) {
    Vue = _Vue;
    // 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
    Vue.mixin({
        beforeCreate() {
            // 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
            if (this.$options.store) {
                // 将store 挂载到原型上
                Vue.prototype.$store = this.$options.store;
            }
        }
    })
}

export default { Store, install }
  1.  通过vue中data是响应式的原理,将options.state放进$$state中进行响应式。
  2. 设置get访问器限制访问,返回出this._vm._data.$$state;

2. store/index.js:

import Vue from 'vue';
import Vuex from '../plugins/vuex'

Vue.use( Vuex );

const store = new Vuex.Store({
    state: {
        num: 100
    },
})
export default store;

3. App.vue:

<template>
  <div>
    {{ $store.state.num  }}
  </div>
</template>

二、修改数据(mutations和actions):

1. plugins/Vuex.js:

let Vue;

class Store {
    constructor(options) {
        // 1. 保存选项 将 store 文件中的 mutations 和 actions 获取到并赋值
        this._mutations = options.mutations || {};
        this._actions = options.actions || {};

        // 2. commit dispatch 绑定this
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)

        // 保存数据
        this._vm = new Vue({
            data: {
                $$state: options.state
            },
        })
    }

    // 代理(设置访问器的方式来限制访问)
    get state() {
        return this._vm._data.$$state;
    }


    // 3. mutations 和 actions 部分
    commit(type, payload) {
        // 通过 this._mutations[type] 获取到具体的 函数
        const entry = this._mutations[type];
        // 当前这个函数存在的话  就进行执行
        entry && entry(this.state, payload)
    }

    dispatch(type, payload) {
        // 通过 this._actions[type] 获取到具体的 异步函数
        const entry = this._actions[type];
        // 这个异步函数存在的话  那么就执行
        entry && entry(this, payload)
    }
}


// 定义一个install方法
function install(_Vue) {
    Vue = _Vue;
    // 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
    Vue.mixin({
        beforeCreate() {
            // 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
            // console.log(this.$options.store);
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store;
            }
        }
    })

}


export default { Store, install }
  1. 首先将传递的mutations和actions绑定到store中
  2. 绑定commit和dispatch的this指向
  3. 通过commit方法的type类型,来找出_mutations中的方法,进行执行。
  4. commit的方法 entry需要传递this.state(state)和payload参数,dispatch方法需要传递上下文this(ctx)

2. store/index.js:

import Vue from 'vue';
import Vuex from '../plugins/vuex'

Vue.use( Vuex );

const store = new Vuex.Store({
    state: {
        num: 100
    },
    mutations: {
        addNum(state,val) {
            state.num += val;
        }
    },
    actions: {
        addAsyncNum(ctx, val) {
            setInterval(()=>{
                ctx.commit('addNum',val)
            },2000)
        }

    },
})

export default store;

3. App.vue:

<template>
  <div>
    store中的数据为------{{ $store.state.num}}
    <button @click="$store.commit('addNum',10)">++</button>
    <button @click="$store.dispatch('addAsyncNum', 20)">Async ++</button>
  </div>
</template>

三、getters方法的实现

1. plugins/Vuex.js:

let Vue;


class Store {
    constructor(options) {
        // 1. 保存选项
        this.wrappedGetters = options.getters || {}

        // 2. 定义 computed 和 getters 属性
        const computed = {}  // 获取到计算成功的数据  挂载到 store._vm上
        this.getters = {}    //  为自身提供一个getters方法 方便展示 计算结果
		
        // 3. 绑定 this 指向
        const store = this;    // 获取到 this 

        // 4. 遍历 this.wrappedGetters 的所有的 key 值
        Object.keys(this.wrappedGetters).forEach(key => {
            // 5. 根据key值  获取到所对应的方法
            const fn = store.wrappedGetters[key];
            // 6. 以 key 为键, 方法为 值,  添加到 computed 中
            computed[key] = () => {
                return fn(store.state)
            }
            
            // 7. 为 this.getters 添加一个键值对,键是key(fil), 
            // 添加了一个展示方法 返回的是 store中的一个计算属性,键名是key(fil)
            // 访问时 调用 getters.fil
            Object.defineProperty(store.getters, key, {
                get() {
                    return store._vm[key]
                }
            })
        })


        // 保存数据
        this._vm = new Vue({
            data: {
                $$state: options.state
            },
            // 8. 将 computed 挂载到 原型上
            computed
        })
    }

    // 代理(设置访问器的方式来限制访问)
    get state() {
        return this._vm._data.$$state;
    }
}

// 定义一个install方法
function install(_Vue) {
    Vue = _Vue;
    // 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
    Vue.mixin({
        beforeCreate() {
            // 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
            // console.log(this.$options.store);
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store;
            }
        }
    })

}

export default { Store, install }
  1. 获取传递的getters参数,保存在store中
  2. 定义computed,将计算成功的数据挂载到store._vm上
  3. 定义getters,展示数据时调用。
  4. 遍历所有的this.wapperGetters,获取到所有的key
  5. 根据key获取到对应的方法,将键值的形式添加到computed中,computed挂载到this._vm上
  6. 通过Object.defineProperty将方法添加到getters中,设置get方法,返回计算后的结果。

2. store/index.js:

import Vue from 'vue';
import Vuex from '../plugins/vuex'

Vue.use( Vuex );

const store = new Vuex.Store({
    state: {
        num: 100
    },
    getters: {
        fil(state) {
            return state.num * 2
        }

    }

})

export default store;

3. App.vue:

<template>
  <div>
    store中的数据为----{{ $store.getters.fil }}
  </div>
</template>

<script>
export default {
 
}

</script>

手捏vuex

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值