面試準備之JavaScript事件模型

janto007發表於2018-03-01

1.事件模型各階段

DOM Level 2 Events(事件模型):捕獲階段-目標階段-冒泡階段
事件監聽:

/*
 *event: 字串,指定事件名
 *function: 指定要事件觸發時執行的函式
 *useCapture: 布林值,指定事件是否在捕獲或冒泡階段執行
 */
element.addEventListener(event, function, useCapture)
複製程式碼

移除事件監聽:

element.removeEventListener(event, function, useCapture)
複製程式碼

Internet Explorer 8 及更早IE版本: 目標階段-冒泡階段
事件監聽:

element.attatchEvent(event, function)
複製程式碼

移除事件監聽:

element.detachEvent(event, function)
複製程式碼

2.事件物件

  • DOM事件模型中的事件物件常用屬性:
    1. type用於獲取事件型別
    2. target獲取事件目標
    3. stopPropagation()阻止事件冒泡
    4. preventDefault()阻止事件預設行為
  • IE事件模型中的事件物件常用屬性:
    1. type用於獲取事件型別
    2. srcElement獲取事件目標
    3. cancelBubble阻止事件冒泡
    4. returnValue阻止事件預設行為

3.事件委託/代理

優勢:

  • 節省記憶體佔用,減少事件註冊
  • 新增子物件時無需再次對其繫結事件,適合動態新增元素

示例:

<ul id="parent">
  <li class="child">one</li>
  <li class="child">two</li>
  <li class="child">three</li>
</ul>

<script type="text/javascript">
  //父元素
  var dom= document.getElementById('parent');

  //父元素繫結事件,代理子元素的點選事件
  dom.onclick= function(event) {
    var event= event || window.event;
    var curTarget= event.target || event.srcElement;

    if (curTarget.tagName.toLowerCase() == 'li') {
      //事件處理
    }
  }
</script>
複製程式碼

4.實現事件模型

編寫bind繫結,trigger觸發函式

function Emitter() {
  this._listener= []; //_listener[自定義的事件名]= [所用執行的匿名函式1,所用執行的匿名函式2,...]
};

Emitter.prototype.bind= function(eventName, handle) {
  var listener= this._listener[eventName] || []; //是否存在eventName事件,否則新建陣列
  listener.push(handle);
  this._listener[eventName]= listener; 
};

Emitter.prototype.trigger= function(eventName) {
  var args= Array.prototype.slice.apply(arguments).slice(1); //取得除eventName之外的其他引數
  var listener= this._listener[eventName];

  if (!Array.isArray(listener)) {
    return false;
  };

  //遍歷事件
  listener.forEach(function(handleFun) {
    try{
      handleFun.apply(this, args);
    }catch (e){
      console.error(e);
    }
  });
};

// 例項
var emitter= new Emitter();

// 繫結函式
emitter.bind('output', function(arguments_1, arguments_2) {
  console.log(arguments_1, arguments_2);
});

//觸發函式
emitter.trigger('output', 'a', 'b');
複製程式碼

5.事件廣播

var event= new Event('build'); 

// listener for the event
element.addEvenetListener('build', function(e) {...}, false);

//Dispatch the event 
element.dispatchEvent(event);
複製程式碼

參考連結

相關文章