Method monitoring in different components of react--eventProxy publish-subscribe mode

1. Demand issues:
Insert picture description here

When doing React-ant-design-mobileAPP projects. When the reset event is determined in the navigation bar, the list page needs to be refreshed. And these two components have nothing to do with each other. At this time, eventProxythe method functions to monitor different components are used.
2,

  • on, one: The on and one functions are used by subscribers to monitor the corresponding events and use the function in response to the event as a parameter. The only difference between on and one is that the function that uses one to subscribe will only be triggered once, while using on The subscribed function will be triggered every time an event occurs.
  • Trigger: Trigger is used by the publisher to publish events, and takes other parameters except the first parameter (event name) as new parameters to trigger the function of subscribing using one and on.
  • off: used to release all functions subscribed to an event.

3. First, you need to import eventProxyfiles.
Put it in a file separately, use script to import, or import important to use eventProxy;

const eventProxy = {
    
    
  onObj: {
    
    },
  oneObj: {
    
    },
  on: function (key, fn) {
    
    
    if (this.onObj[key] === undefined) {
    
    
      this.onObj[key] = [];
    }
    const args = [].concat(Array.prototype.slice.call(arguments, 1));
    for (let i = 0; i < args.length; i++) {
    
    
      this.onObj[key].push(args[i]);
    }
  },
  one: function (key, fn) {
    
    
    if (this.oneObj[key] === undefined) {
    
    
      this.oneObj[key] = [];
    }

    this.oneObj[key].push(fn);
  },
  off: function (key) {
    
    
    this.onObj[key] = [];
    this.oneObj[key] = [];
  },
  trigger: function () {
    
    
    let key, args;
    if (arguments.length == 0) {
    
    
      return false;
    }
    key = arguments[0];
    args = [].concat(Array.prototype.slice.call(arguments, 1));
    if (this.onObj[key] !== undefined
      && this.onObj[key].length > 0) {
    
    
      for (let i in this.onObj[key]) {
    
    
        this.onObj[key][i].call(null, args[i]);
      }
    }
    if (this.oneObj[key] !== undefined
      && this.oneObj[key].length > 0) {
    
    
      for (let i in this.oneObj[key]) {
    
    
        this.oneObj[key][i].apply(null, args);
        this.oneObj[key][i] = undefined;
      }
      this.oneObj[key] = [];
    }
  }
};

export default eventProxy;

4. Use

  • In the component method that needs to be monitored:
  • import eventProxy from '../../utils/eventProxy' Import file
  • In the method that needs to be monitored,
    I am here to determine the event
  queryClick = () => {
    
    
   eventProxy.trigger('query', 'list')
    this.setState({
    
    
      visible: false,
    })
  }

  • Then use it in the component that needs to perform the corresponding action
  • In the componentDidMountgo use

  componentDidMount() {
    
    
    // 清除事件监听
    eventProxy.on('query', () => {
    
    
      this.getDynamicsList()
    })
    // eventProxy.on('clear', () => {
    
    
    //   this.getDynamicsList()
    // })
  }

After use, be sure to clear the event listener when the component is uninstalled

  componentWillUnmount = () => {
    
    
    // 清除监听
    eventProxy.off('query', '');
  }

5. In this way, the different component methods and events are connected.

Can refer to-appearance mode

The appearance mode is a relatively simple and ubiquitous mode. The appearance mode provides a high-level interface, which makes the client or subsystem more convenient to call. Expressed in a piece of code that couldn't be more simple:

Implement a simple subscription publisher/
observer model, which defines a one-to-many dependency relationship between objects. When the state of an object changes, all objects that depend on it will be notified.
In fact, as long as you have ever bound an event function to a DOM node, then you have used the observer mode!
document.body.addEventListener('click', function () { alert(2); });

But this is just the simplest use of the observer mode. In many scenarios, we often implement some custom events to meet our needs.
For example:
you go to a company to apply for a job, and after a talk, hr tells you: "Okay, you go back and wait for the notice!".
At this time, 1. You will ask the company's phone number, and then call it every day to ask the result
2. Leave your mobile phone number to hr, and then wait for him to call you

I believe that many times, everyone chooses the latter.
In case you bother him by calling hr every day, maybe he originally planned to recruit you, and now he doesn't plan to attack you anymore!
Then at this time, hr is equivalent to a publisher, and you are a subscriber!
Well, most people who ask you to go back and wait for the news are no help...
I have also encountered a company that does not even notify you if you are not admitted!
So how should a simple observer pattern be implemented?
To specify a publisher;
add a cache list to the publisher to store callback functions to notify subscribers; (many people from this company come to apply) When the
message is finally published, the publisher will traverse the cache list and trigger it in turn Stored subscriber callback function; (you up or you over)

var event = {
    
    }; //发布者(hr)
event.clietList = []; //发布者的缓存列表(应聘者列表)
event.listen = function(fn) {
    
     //增加订阅者函数
this.clietList.push(fn);
};
event.trigger = function() {
    
     //发布消息函数
for (var i = 0; i < this.clietList.length; i++) {
    
    
    var fn = this.clietList[i];
    fn.apply(this, arguments);
}
};
event.listen(function(time) {
    
     //某人订阅了这个消息
console.log('正式上班时间:' + time);
});
event.trigger('2016/10',yes); //发布消息
//输出 正式上班时间:2016/10
到这里,我们已经实现了一个最简单的观察者模式了!
但是上面的函数其实存在一个问题,那就是发布者没办法选择自己要发布的消息类型!
比如这家公司同时在招php,web前端,如果使用上面的函数就没办法区分职位了!只能一次性把全部订阅者都发送一遍消息。
对上面的代码进行改写:
var event = {
    
    }; //发布者(hr)
event.clietList = []; //发布者的缓存列表(应聘者列表)
event.listen = function(key, fn) {
    
     //增加订阅者函数
if (!this.clietList[key]) {
    
    
    this.clietList[key] = [];
}
this.clietList[key].push(fn);
};
event.trigger = function() {
    
     //发布消息函数
var key = Array.prototype.shift.call(arguments),
    fns = this.clietList[key];
for (var i = 0; i < fns.length; i++) {
    
    
    var fn = fns[i];
    fn.apply(this, arguments);
}
};
event.listen('web前端', fn1 = function(time) {
    
     //小强订阅了这个消息。
console.log('姓名:小强');
console.log('正式上班时间:' + time);
});
event.listen('web前端', fn2 = function(time) {
    
     //大大强订阅了这个消息
console.log('姓名:大大强');
console.log('正式上班时间:' + time);
});
//发布者发布消息
event.trigger('web前端','小强', '2016/10'); //姓名:小强 正式上班时间:2016/10
event.trigger('php','大大强', '2016/15'); //姓名:大大强 正式上班时间:2016/15
通过添加了一个key,我们实现了对职位的判断。
有了订阅事件,我们怎么能少了取消订阅事件呢?
event.remove = function(key, fn) {
    
    
var fns = this.clietList[key];
if (!fns) {
    
    
    return false;
}
if (!fn) {
    
     //如果没有传入fn回调函数,直接取消key对应消息的所有订阅
    this.clietList[key] = [];
} else {
    
    
    for (var i = 0; i < fns.length; i++) {
    
     //遍历回调函数列表
        var _fn = fns[i];
        if (_fn === fn) {
    
    
            fns.splice(i, 1); //删除订阅者的回调函数
        }
    }
}
};
//这时候必须指定回调函数,否则无法在remove函数中进行对比删除。
event.listen('web前端', fn1 = function(time) {
    
     //小强订阅了这个消息。
console.log('姓名:小强');
console.log('正式上班时间:' + time);
});
event.listen('web前端', fn2 = function(time) {
    
     //大大强订阅了这个消息
console.log('姓名:大大强');
console.log('正式上班时间:' + time);
});
event.remove('web前端',fn1);
//发布者发布消息
event.trigger('web前端','2016/10');
//输出 姓名:大大强 正式上班时间:2016/10

Improve the above code, create a global object to implement the observer mode,
use closures to implement private variables, and expose only the necessary APIs to users:

var event = (function() {
    
    
var clietList = []; //发布者的缓存列表(应聘者列表)

var listen = function(key, fn) {
    
     //增加订阅者函数
    if (!this.clietList[key]) {
    
    
        this.clietList[key] = [];
    }
    this.clietList[key].push(fn);
};

var trigger = function() {
    
     //发布消息函数
    var key = Array.prototype.shift.call(arguments),
        fns = this.clietList[key];
    for (var i = 0; i < fns.length; i++) {
    
    
        var fn = fns[i];
        fn.apply(this, arguments);
    }
};

var remove = function(key, fn) {
    
    
    var fns = this.clietList[key];
    if (!fns) {
    
    
        return false;
    }
    if (!fn) {
    
     //如果没有传入fn回调函数,直接取消key对应消息的所有订阅
        this.clietList[key] = [];
    } else {
    
    
        for (var i = 0; i < fns.length; i++) {
    
     //遍历回调函数列表
            var _fn = fns[i];
            if (_fn === fn) {
    
    
                fns.splice(i, 1); //删除订阅者的回调函数
            }
        }
    }
};

return{
    
    
    listen:listen,
    trigger:trigger,
    remove:remove
}
})();
观察者模式进阶:
使用命名空间防止事件名冲突
实现先发布后订阅功能
[观察者模式引自原作者](https://segmentfault.com/a/1190000023447952) 

Guess you like

Origin blog.csdn.net/weixin_45416217/article/details/107702580