[TOC]
事件处理程序
事件处理程序又叫事件监听器,实际上就是事件绑定函数。事件发生时,会执行相应的代码
事件处理机制分为4类
- DOM0级处理程序
- IE事件处理程序
- DOM2级事件处理程序
- html事件处理程序
html事件处理程序
<div id="divA" onClick="this.innerHTML = 'BBB'">AAA</div> <!-- this的应用 --> <script> function divClick() { divA.innerHTML = 'CCC'; } </script> <!-- id的应用 --> <button onClick="divClick()">id的直接应用</button> <!-- event对象的应用 --> <div onClick="this.innerHTML += event.type">event对象的应用</div> <!-- 属性的应用 --> <button onClick="this.innerHTML = value" value="属性的应用">value</button> <script> var value = '123'; </script> <intpu type="text" onClick="alert(value)"/> <!-- 注意 <script> var value = '123'; </script> <input type="text" onClick="alert(value)"/> 此时输出"" --> <form> <input type="text" name="username" value="123"/> <input type="button" value="按钮" onClick="alert(username.value)"/> </form> <!-- 此时this作用域链是 this->this.form->document function中的this不等于document中的this -->
DOM0级处理程序
<div id="box"></div> <script> box.onclick = function(event){ this.innerHTML += 1; // 此时this与dom中一致 } box.onclick = null; // 清楚此事件 // 每个事件目标对于每一种事件类型,只能添加一个事件处理程序。 </script>
DOM2级事件处理程序
<div id="box"></div> <script> // IE8以上就支持这种语法了 function a(){ // ... } // 参数列表:事件类型,事件触发函数,事件处理类型ture捕获,false冒泡,默认为冒泡 box.addEventListener('click', a, true); box.removeEventListener('click', '事件触发函数名'); // addEventListener此种方式支持添加多个相同事件,以添加顺序执行触发顺序 </script>
IE事件处理程序
```html<a name="z1J20"></a> ## 四种事件的顺序 DOM0级会覆盖HTML事件处理程序<br />chrome,opera,safari等webkit内核会按定义顺序执行<br />firefox和ie优先执行DOM0级 <a name="lkO6t"></a> ### 浏览器默认行为与冒泡 event.preventDefault ? event.preventDefault() : (event.returnValue = false); <a name="Ta8rN"></a> ### 阻止默认行为 return false; 也能阻止默认行为,并且在jquery中还能阻止冒泡 event.stopPropagetion ? event.stopPropagation() : (window.event.cancelBubble = true); <a name="44VoE"></a> ### event.repeat 是返回键盘长按事件的,首次触发会返回false,在部分浏览器中,例如window中,有可能长按会无数次触发事件,加入下面代码可以解决此问题<br />if (event.repeat) {<br />return<br />} <a name="ET7G3"></a> ### 自定义事件 ```javascript var eventTarget = function() { this.__listener = {}; } eventTarget.prototype = { addEvents:function(){}, fireEvents:function(){}, removeEvents:function(){}, } var myEvents = new eventTarget(); myEvents.addEvents( { "once": function () { // click alert('只出现一次') this.removeEvents('once') }, "infinity": function() { // click alert('每次都执行'); } }); document.onclick = function(){ // 监听 e = e || window.event; var target = e.target || e.srcElemet; if (!target || !/input|pre/i.test(target.tarName)) { myEvent.fireEvents(["onec","infinity"]); } } divA.addEventListener('alert', function(){ alert('alert'); }, false); console.log(divA); divA.addEventListener('click', function(){ alert('666'); var evt = document.createEvent('MouseEvent'); evt.initMouseEvent('alert', false, false); // var evt = document.createEvent('HTMLEvents'); // evt.initEvent('alert', false, false); // 两种都可以 divA.dispatchEvent(evt); }, true); // event-emitter
观察者模型
/** * @description 观察者列表(目标) */ class ObserverList { constructor() { this.observerList = [] } add(observer) { return this.observerList.push(observer); } remove(observer) { this.observerList = this.observerList.filter(ob => ob !== observer); } count() { return this.observerList.length; } get(index) { return this.observerList[index]; } } /** * @description 事件调度对象 */ class PubSub { constructor() { this.subscribers = {} } subscribe(type, fn) { if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) { this.subscribers[type] = []; } this.subscribers[type].push(fn); } unsubscribe(type, fn) { let listeners = this.subscribers[type]; if (!listeners || !listeners.length) return; this.subscribers[type] = listeners.filter(v => v !== fn); } publish(type, ...args) { let listeners = this.subscribers[type]; if (!listeners || !listeners.length) return; listeners.forEach(fn => fn(...args)); } } class SubjectClass { // 观察者列表 this.observers = new ObserverList(); // 观察者模式的方法 this.addObserver = function (observer) { this.observers.add(observer); } // 观察者模式的方法 this.removeObserver = function (observer) { this.observers.remove(observer); } // 通知观察者更新 this.notify = function (options) { let obCount = this.observers.count(); for (let index = 0; index < obCount; index++) { if (this.observers.get(index).update) { this.observers.get(index).update(options); } } } // 事件调度对象 this.pubSub = new PubSub(); }