├── .gitignore ├── README.md ├── README.zh-cn.md ├── dist ├── vue-event-proxy.js └── vue-event-proxy.min.js ├── package.json └── src └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /.idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue Event Proxy 2 | 3 | [![npm](https://img.shields.io/npm/v/vue-event-proxy.svg)](https://www.npmjs.com/package/vue-event-proxy) 4 | [![](https://img.shields.io/badge/zh--cn-中文-orange.svg)](https://github.com/jser-club/vue-event-proxy/blob/master/README.zh-cn.md) [![](https://img.shields.io/badge/en--us-英语-green.svg)](https://github.com/jser-club/vue-event-proxy/blob/master/README.md) 5 | 6 | ## Introduction 7 | 8 | The Library that let Vue.js support global events, just 1.79kb after compression. 9 | 10 | 1. Global events are implemented by adding a prefix 11 | 2. Registered event will be removed when component is destroyed 12 | 13 | Demo: [CodeSandbox](https://codesandbox.io/s/xlvz2p79vp) 14 | 15 | ## install 16 | ``` 17 | $ npm install --save vue-event-proxy 18 | ``` 19 | 20 | 21 | ## Usage 22 | Just add `global:` prefix to first argument of methods: `$on`, `$emit`, `$once` 23 | 24 | ```js 25 | import EventProxy from 'vue-event-proxy'; 26 | Vue.use(EventProxy); 27 | 28 | this.$on('global:EVENT_NAME'); 29 | this.$once('global:EVENT_NAME'); 30 | this.$emit('global:EVENT_NAME'); 31 | ``` 32 | 33 | More see: [https://cn.vuejs.org/v2/api/#vm-on](https://cn.vuejs.org/v2/api/#vm-on) 34 | -------------------------------------------------------------------------------- /README.zh-cn.md: -------------------------------------------------------------------------------- 1 | # Vue Event Proxy 2 | 3 | [![npm](https://img.shields.io/npm/v/vue-event-proxy.svg)](https://www.npmjs.com/package/vue-event-proxy) [![](https://img.shields.io/badge/zh--cn-中文-orange.svg)](https://github.com/jser-club/vue-event-proxy/blob/master/README.zh-cn.md) [![](https://img.shields.io/badge/en--us-英语-green.svg)](https://github.com/jser-club/vue-event-proxy/blob/master/README.md) 4 | 5 | ## 介绍 6 | 7 | 让Vue.js支持全局事件的库,压缩完只有 `1.79kb`。 8 | 9 | 1. 通过增加前缀实现全局事件 10 | 2. 组件销毁自动移除注册的事件 11 | 12 | 线上实例: [CodeSandbox](https://codesandbox.io/s/xlvz2p79vp) 13 | 14 | ## 安装 15 | ``` 16 | $ npm install --save vue-event-proxy 17 | ``` 18 | 19 | ## 使用 20 | 只需要在 `$on`、`$emit`、`$once` 方法的第一个参数参数添加 `global:` 前缀 21 | 22 | ```js 23 | import EventProxy from 'vue-event-proxy'; 24 | Vue.use(EventProxy); 25 | 26 | this.$on('global:EVENT_NAME'); 27 | this.$once('global:EVENT_NAME'); 28 | this.$emit('global:EVENT_NAME'); 29 | ``` 30 | 31 | 更多: [https://cn.vuejs.org/v2/api/#vm-on](https://cn.vuejs.org/v2/api/#vm-on) 32 | -------------------------------------------------------------------------------- /dist/vue-event-proxy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); 8 | 9 | function plugin(Vue) { 10 | var version = Number(Vue.version.split('.')[0]); 11 | var NOOP = function NOOP() {}; 12 | if (version < 2) { 13 | console.error('[vue-event-proxy] only support Vue 2.0+'); 14 | return; 15 | } 16 | 17 | // Exit if the plugin has already been installed. 18 | if (plugin.installed) { 19 | return; 20 | } 21 | plugin.installed = true; 22 | 23 | var eventMap = {}; 24 | var vmEventMap = {}; 25 | var globalRE = /^global:/; 26 | 27 | function mixinEvents(Vue) { 28 | var on = Vue.prototype.$on; 29 | Vue.prototype.$on = function proxyOn(eventName) { 30 | var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : NOOP; 31 | 32 | var vm = this; 33 | if (Array.isArray(eventName)) { 34 | eventName.forEach(function (item) { 35 | vm.$on(item, fn); 36 | }); 37 | } else { 38 | if (globalRE.test(eventName)) { 39 | (vmEventMap[vm._uid] || (vmEventMap[vm._uid] = [])).push(eventName); 40 | (eventMap[eventName] || (eventMap[eventName] = [])).push(vm); 41 | } 42 | on.call(vm, eventName, fn); 43 | } 44 | return vm; 45 | }; 46 | 47 | var emit = Vue.prototype.$emit; 48 | Vue.prototype.$emit = function proxyEmit(eventName) { 49 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 50 | args[_key - 1] = arguments[_key]; 51 | } 52 | 53 | var vm = this; 54 | if (globalRE.test(eventName)) { 55 | var vmList = eventMap[eventName] || []; 56 | vmList.forEach(function (item) { 57 | return emit.apply(item, [eventName].concat(args)); 58 | }); 59 | } else { 60 | emit.apply(vm, [eventName].concat(args)); 61 | } 62 | return vm; 63 | }; 64 | } 65 | 66 | function applyMixin(Vue) { 67 | Vue.mixin({ 68 | beforeDestroy: function beforeDestroy() { 69 | var vm = this; 70 | var events = vmEventMap[vm._uid] || []; 71 | events.forEach(function (event) { 72 | var targetIdx = eventMap[event].findIndex(function (item) { 73 | return item._uid === vm._uid; 74 | }); 75 | eventMap[event].splice(targetIdx, 1); 76 | }); 77 | delete vmEventMap[vm._uid]; 78 | Object.entries(eventMap).forEach(function (_ref) { 79 | var _ref2 = _slicedToArray(_ref, 2), 80 | eventName = _ref2[0], 81 | vmList = _ref2[1]; 82 | 83 | return vmList.length || delete eventMap[eventName]; 84 | }); 85 | } 86 | }); 87 | } 88 | 89 | mixinEvents(Vue); 90 | applyMixin(Vue); 91 | } 92 | 93 | exports.default = plugin; 94 | -------------------------------------------------------------------------------- /dist/vue-event-proxy.min.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:true});var _slicedToArray=function(){function t(r,e){var t=[];var n=true;var i=false;var o=undefined;try{for(var u=r[Symbol.iterator](),a;!(n=(a=u.next()).done);n=true){t.push(a.value);if(e&&t.length===e)break}}catch(r){i=true;o=r}finally{try{if(!n&&u["return"])u["return"]()}finally{if(i)throw o}}return t}return function(r,e){if(Array.isArray(r)){return r}else if(Symbol.iterator in Object(r)){return t(r,e)}else{throw new TypeError("Invalid attempt to destructure non-iterable instance")}}}();function plugin(r){var e=Number(r.version.split(".")[0]);var o=function r(){};if(e<2){console.error("[vue-event-proxy] only support Vue 2.0+");return}if(plugin.installed){return}plugin.installed=true;var l={};var u={};var f=/^global:/;function t(r){var i=r.prototype.$on;r.prototype.$on=function r(e){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:o;var n=this;if(Array.isArray(e)){e.forEach(function(r){n.$on(r,t)})}else{if(f.test(e)){(u[n._uid]||(u[n._uid]=[])).push(e);(l[e]||(l[e]=[])).push(n)}i.call(n,e,t)}return n};var a=r.prototype.$emit;r.prototype.$emit=function r(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i {}; 4 | if (version < 2) { 5 | console.error('[vue-event-proxy] only support Vue 2.0+'); 6 | return; 7 | } 8 | 9 | // Exit if the plugin has already been installed. 10 | if (plugin.installed) { 11 | return; 12 | } 13 | plugin.installed = true 14 | 15 | const eventMap = {}; 16 | const vmEventMap = {}; 17 | const globalRE = /^global:/ 18 | 19 | function mixinEvents(Vue) { 20 | const on = Vue.prototype.$on; 21 | Vue.prototype.$on = function proxyOn(eventName, fn = NOOP) { 22 | const vm = this; 23 | if (Array.isArray(eventName)) { 24 | eventName.forEach((item) => { 25 | vm.$on(item, fn) 26 | }); 27 | } else { 28 | if (globalRE.test(eventName)) { 29 | (vmEventMap[vm._uid] || (vmEventMap[vm._uid] = [])).push(eventName); 30 | (eventMap[eventName] || (eventMap[eventName] = [])).push(vm); 31 | } 32 | on.call(vm, eventName, fn); 33 | } 34 | return vm; 35 | }; 36 | 37 | const emit = Vue.prototype.$emit; 38 | Vue.prototype.$emit = function proxyEmit(eventName, ...args) { 39 | const vm = this; 40 | if (globalRE.test(eventName)) { 41 | const vmList = eventMap[eventName] || []; 42 | vmList.forEach(item => emit.apply(item, [eventName, ...args])); 43 | } else { 44 | emit.apply(vm, [eventName, ...args]); 45 | } 46 | return vm; 47 | } 48 | } 49 | 50 | function applyMixin(Vue) { 51 | Vue.mixin({ 52 | beforeDestroy() { 53 | const vm = this; 54 | const events = vmEventMap[vm._uid] || []; 55 | events.forEach((event) => { 56 | const targetIdx = eventMap[event].findIndex(item => item._uid === vm._uid); 57 | eventMap[event].splice(targetIdx, 1); 58 | }); 59 | delete vmEventMap[vm._uid]; 60 | Object.entries(eventMap).forEach( 61 | ([eventName, vmList]) => vmList.length || delete eventMap[eventName] 62 | ); 63 | }, 64 | }); 65 | } 66 | 67 | mixinEvents(Vue); 68 | applyMixin(Vue); 69 | } 70 | 71 | export default plugin; 72 | --------------------------------------------------------------------------------