const events = Symbol.for('events'); const check = Symbol.for('check'); /** * 事件存储的位置 * @example * this[delegate] = { * [事件类型]: { * [选择器类型]: Function * } * } * 事件类型 代表 [click | mouseover | mousemove | touch ...] * 选择器类型暂时只有 label和class两个值 */ const delegate = Symbol.for('delegate'); const props = Symbol.for('props'); //获取selector类型,是class选择器还是标签选择器 const getSelectorType = Symbol.for('getSelectorType'); const noDelegation = Symbol.for('noDelegation') const truelyHandler = Symbol.for('truelyHandler'); const checkStrategies = { class: function(selector, childNode, parentNode) { const classname = childNode.className; if(classname && classname.split){ const ary = classname.split(' '); if(~ ary.indexOf(selector) ){ return true; } else if( childNode == parentNode || childNode == document.querySelector('html') ) { return false; } else if( !childNode.parentNode ){ return false; } else { return checkStrategies.class(selector, childNode.parentNode, parentNode) } } else { if( childNode == parentNode || childNode == document.querySelector('html') ) { return false; } return checkStrategies.class(selector, childNode.parentNode, parentNode) } }, id: function(selector, childNode, parentNode) { const id = childNode.getAttribute('id'); if(id && id == selector){ return true; } if( childNode == parentNode || childNode == document.querySelector('html') ){ return false; } return checkStrategies.id(selector, childNode.parentNode, parentNode); }, label: function(selector, childNode, parentNode) { const label = childNode.tagName.toLowerCase(); if(label == selector){ return true; } if( childNode == parentNode || childNode == document.querySelector('html') ){ return false; } return checkStrategies.label(selector, childNode.parentNode, parentNode); } } class Base { constructor(props) { /** * @member {Map} Symbol.for('events') - 用来保存事件的 */ this[events] = {}; this[delegate] = {}; this[truelyHandler] = {}; this[props] = ['after', 'before', 'listen', 'trigger', 'remove', '$', 'on', 'off', 'destroy']; if(props && props.$el){ this.$el = props.$el; } } /** * aop after * @param {String} fn - 方法名字 * @param {Function} callback - 回调方法 */ after(fn, callback) { const f = this[fn]; const me = this; if(~this[props].indexOf(fn)){ return ; } me[fn] = function() { const ret = f.apply(me, arguments); callback.apply(me, arguments); return ret; } } /** * aop before * @param {String} fn - 方法名字 * @param {Function} callback - 回调方法 */ before(fn, callback) { const f = this[fn]; const me = this; if(~this[props].indexOf(fn)){ return ; } me[fn] = function() { callback.apply(me, arguments); const ret = f.apply(me, arguments); return ret; } } /** * 监听事件 * @param {String} name - 事件名称 * @param {Funciton} handler - 处理器 * @example * this.listen('event-click', clickMe); * var clickMe = function(){ console.log('I was clicked') } */ listen(name, handler) { const me = this; const ary = this[events]; if( !ary[name] ){ ary[name] = [] } ary[name].push(handler); return me; } /** * 触发器 * @param {String} name - 事件名称 * @example * this.trigger('event-click'); */ trigger(name, ...arg) { const me = this; const ary = me[events]; if(!ary[name]){ return me; } const handlers = ary[name].slice(0); let fn = null; while(fn = handlers.shift()) { fn.apply(me, arg); } return me; } /** * 移除事件 * @param {String} name - event name */ remove(name) { const me = this; me[events][name] = [] return me; } /** * 选择$el内部dom * @param {String} selector - 选择器,只能是classname * @return {DOM} */ $(selector) { const me = this; return me.$el && me.$el.querySelectorAll(selector); } /** * 获取子选择器类型 * @return {Map} - {type: 'class', selector: 'js-selector'} */ [getSelectorType] (selector) { if(/^\./.test(selector)){ return { type: 'class', selector: selector.slice(1) } } else if(/^\#/.test(selector)) { return { type: 'id', selector: selector.slice(1) } } else { return { type: 'label', selector: selector } } } /** * 事件绑定 * @param {String} name - event name * @param {Function} handler - function * @param {String} targetSelector - 子选择器 * @return {this} * @example * this.on('click', handler, '.js-target'); */ on(name, handler, targetSelector) { const me = this; const _handler = handler; let ret = null; const fn = (e, ...arg) => { const target = e.target; const eventName = e.type.toLowerCase(); //如果未缓存事件,退出 if(!me[delegate][eventName]){ return ; } const handlers = me[delegate][eventName]; for(let key in handlers){ if(key === me[delegate][name][noDelegation]){ handlers[key].forEach((fn) => { fn(e, ...arg); }) } else { handlers[key].forEach((fn) => { ret = me[getSelectorType](key) const recursion = checkStrategies[ret.type] if(recursion && recursion( ret.selector, target, me.$el )){ fn(e, ...arg); } }) } } }; if( !me[truelyHandler][name] ){ me[truelyHandler][name] = fn; me.$el.addEventListener(name, fn, false); } if(!me[delegate][name]){ me[delegate][name] = {}; } if(targetSelector){ if(!me[delegate][name][targetSelector]){ me[delegate][name][targetSelector] = []; } me[delegate][name][targetSelector].push(_handler.bind(me)); } else { if(!me[delegate][name][noDelegation]){ me[delegate][name][noDelegation] = []; } me[delegate][name][noDelegation].push(_handler.bind(me)); } return me; } /** * 解绑 * @param {String} name - event name * @param {[String]} selector - 操作 */ off(name, selector) { const me = this; if( !(me[delegate][name]) ) { return me; } if(!selector) { if(me[truelyHandler][name]){ me.$el.removeEventListener(name, me[truelyHandler][name], false); me[truelyHandler][name] = null; } me[delegate][name] = null; return me; } else { if(me[delegate][name] && me[delegate][name][selector]){ delete me[delegate][name][selector] } } return me; }
export default Base
功能:
1、aop
2、自定义事件
3、dom event