使用 Proxy | Reflect 做数据劫持 | 全局数据监听

使用 Proxy | Reflect 做数据劫持 | 全局数据监听

>  使用demo

import globalData from './globalData'

const {userInfo} = globalData
userInfo.watch('name', str =>{
    console.log('My name is:',str)
})
userInfo.name = 'xxxxxxx'

 

> globalData.js

 

import _event from "./event";

const validator = {
  set: function (target, prop, value) {
    target.emit(prop, value);
    return Reflect.set(...arguments);
  },
  get: function () {
    return Reflect.get(...arguments);
  },
};
const creat = (defaultData = {}) => {
  return new Proxy(
    Object.assign(Object.create(_event), defaultData),
    validator
  );
};

const globalData = {
  userInfo: creat({}),
};

export default globalData;

 

> event.js

 

function Events() {
    // 放置所有添加的 监听事件
    this._events = {};
}
Events.prototype = {
    on: function (name, fn, ...argOrg) {
        // 必传参数验证
        if (!name || !fn) {
            throw new Error(`[Events TypeError] Failed to execute 'Events' on '${name}' : 2 arguments required`);
        }
        // 阻止重复添加相同的监听
        let fns = this._events[name] || [];
        if (fns.find((item) => item.fnOrg === fn)) {
            return;
        }
        this._events[name] = fns.concat({
            fn: (arg) => fn.apply(null, [...argOrg, ...arg]),
            fnOrg: fn
        });
    },
    watch() {
        this.on(...arguments);
    },
    once: function (name, fn, ...argOrg) {
        const onFn = (...arg) => {
            fn.apply(null, arg);
            this.off(name, onFn);
        };
        this.on(name, onFn, ...argOrg);
    },
    emit: function (name, ...arg) {
        (this._events[name] || []).forEach((item) => {
            item.fn(arg);
        });
    },
    off: function (name, fn) {
        // 无参数 : 清掉所有监听
        if (!arguments.length) {
            this._events = Object.create(null);
        }
        // 一个参数 : 清掉该事件名下所有监听
        if (arguments.length == 1) {
            delete this._events[name];
        }
        let fns = this._events[name];
        if (!fns || !fns.length) return;
        this._events[name] = (fns || []).filter((item) => {
            return item.fnOrg !== fn;
        });
    }
};
export default new Events();

 

posted @ 2020-05-19 09:29  Tommy_marc  阅读(370)  评论(0编辑  收藏  举报