vue-event-proxy

  1. function plugin(Vue) {
  2. const version = Number(Vue.version.split('.')[0]);
  3. const NOOP = () => {};
  4. if (version < 2) {
  5. console.error('[vue-event-proxy] only support Vue 2.0+');
  6. return;
  7. }
  8. // Exit if the plugin has already been installed.
  9. if (plugin.installed) {
  10. return;
  11. }
  12. plugin.installed = true
  13. const eventMap = {};
  14. const vmEventMap = {};
  15. const globalRE = /^global:/
  16. function mixinEvents(Vue) {
  17. const on = Vue.prototype.$on;
  18. Vue.prototype.$on = function proxyOn(eventName, fn = NOOP) {
  19. const vm = this;
  20. if (Array.isArray(eventName)) {
  21. eventName.forEach((item) => {
  22. vm.$on(item, fn)
  23. });
  24. } else {
  25. if (globalRE.test(eventName)) {
  26. (vmEventMap[vm._uid] || (vmEventMap[vm._uid] = [])).push(eventName);
  27. (eventMap[eventName] || (eventMap[eventName] = [])).push(vm);
  28. }
  29. on.call(vm, eventName, fn);
  30. }
  31. return vm;
  32. };
  33. const emit = Vue.prototype.$emit;
  34. Vue.prototype.$emit = function proxyEmit(eventName, ...args) {
  35. const vm = this;
  36. if (globalRE.test(eventName)) {
  37. const vmList = eventMap[eventName] || [];
  38. vmList.forEach(item => emit.apply(item, [eventName, ...args]));
  39. } else {
  40. emit.apply(vm, [eventName, ...args]);
  41. }
  42. return vm;
  43. }
  44. }
  45. function applyMixin(Vue) {
  46. Vue.mixin({
  47. beforeDestroy() {
  48. const vm = this;
  49. const events = vmEventMap[vm._uid] || [];
  50. events.forEach((event) => {
  51. const targetIdx = eventMap[event].findIndex(item => item._uid === vm._uid);
  52. eventMap[event].splice(targetIdx, 1);
  53. });
  54. delete vmEventMap[vm._uid];
  55. Object.entries(eventMap).forEach(
  56. ([eventName, vmList]) => vmList.length || delete eventMap[eventName]
  57. );
  58. },
  59. });
  60. }
  61. mixinEvents(Vue);
  62. applyMixin(Vue);
  63. }
  64. export default plugin;