사용자 정의 events_javascript 기술의 javascript 구현에 대한 자세한 설명

WBOY
풀어 주다: 2016-05-16 15:19:21
원래의
1224명이 탐색했습니다.

DOM을 운영할 때 일반적으로 onclick, onmouseover 및 일련의 브라우저별 동작 이벤트를 사용합니다.
따라서 사용자 정의 이벤트는 이름에서 알 수 있듯이 자신만의 이벤트 유형과 이벤트 처리 기능을 정의하는 것입니다. 적시에 어떤 이벤트 유형이 필요한지, 어떤 핸들러를 호출할 수 있습니다

1.js에서 지원하는 브라우저 기본 이벤트

특정 브라우저 동작에 대한 이벤트, 시스템 이벤트, js 기본 이벤트 등은 모두 괜찮습니다. 아래에서는 이를 js 기본 이벤트라고 부르겠습니다.
나는 모두가 다음과 같은 이벤트 바인딩 및 js 기본 이벤트의 이벤트 제거와 같은 일련의 작업을 사용해 왔다고 생각합니다.

//DOM0级事件处理程序
var oDiv = document.getElementById('oDiv');
oDiv.onclick = function(){
  alert("你点击了我");
}

로그인 후 복사

또는

//DOM2级事件处理程序
var oDiv = document.getElementById('oDiv');

//非ie
oDiv.addEventListener("click",function(){
  alert("你点击了我");
},false); 

//ie
oDiv.attachEvent("onclick", function(){
  alert("你点击了我");
});

로그인 후 복사

결국, js 사용자 정의 이벤트에 대해 논의하지 않겠습니다. 다음은 js 기본 이벤트를 처리하기 위해 캡슐화한 코드입니다.

//跨浏览器的事件处理程序 
//调用时候直接用domEvent.addEvent( , , );直接调用 
//使用时候,先用addEvent添加事件,然后在handleFun里面直接写其他函数方法,如getEvent; 
//addEventListener和attachEvent---都是dom2级事件处理程序 
var domEvent = { 
  //element:dom对象,event:待处理的事件,handleFun:处理函数 
  //事件名称,不含“on”,比如“click”、“mouseover”、“keydown”等 
  addEvent:function(element,event,handleFun){ 
    //addEventListener----应用于mozilla 
    if(element.addEventListener){ 
      element.addEventListener(event,handleFun,false); 
    }//attachEvent----应用于IE 
    else if(element.attachEvent){ 
      element.attachEvent("on"+event,handleFun); 
    }//其他的选择dom0级事件处理程序 
    else{ 
      //element.onclick===element["on"+event]; 
      element["on"+event] = handleFun; 
    } 
  }, 
  //事件名称,含“on”,比如“onclick”、“onmouseover”、“onkeydown”等 
  removeEvent:function(element,event,handleFun){ 
    //removeEventListener----应用于mozilla 
    if (element.removeEventListener) { 
      element.removeEventListener(event,handleFun,false); 
    }//detachEvent----应用于IE 
    else if (element.detachEvent) { 
      element.detachEvent("on"+event,handleFun); 
    }//其他的选择dom0级事件处理程序 
    else { 
      element["on"+event] = null; 
    } 
  }, 
  //阻止事件冒泡 
  stopPropagation:function(event){ 
    if(event.stopPropagation){ 
      event.stopPropagation(); 
    }else{ 
      event.cancelBubble = true;//IE阻止事件冒泡,true代表阻止 
    } 
  }, 
  //阻止事件默认行为 
  preventDefault:function(event){ 
    if(event.preventDefault){ 
      event.preventDefault(); 
    }else{ 
      event.returnValue = false;//IE阻止事件冒泡,false代表阻止 
    } 
  }, 
  //获得事件元素 
  //event.target--非IE 
  //event.srcElement--IE 
  getElement:function(event){ 
    return event.target || event.srcElement; 
  }, 
  //获得事件 
  getEvent:function(event){ 
    return event? event : window.event; 
  }, 
  //获得事件类型 
  getType:function(event){ 
    return event.type; 
  } 
}; 
로그인 후 복사

다음 주제인 js 커스텀 이벤트를 계속 진행하겠습니다

2. 객체 리터럴은 js 사용자 정의 이벤트를 캡슐화합니다

위의 패키지에 따르면 이렇게 생각할 수 있습니다

var eventTarget = {
  addEvent: function(){
    //添加事件
  },
  fireEvent: function(){
    //触发事件
  },
  removeEvent: function(){
    //移除事件
  }
};
로그인 후 복사

이것이 모든 사람이 이해하기 더 쉽다고 생각합니다. 그리고 여러분이 생각할 수 있는 또 다른 질문이 있습니다. 즉, js 기본 이벤트는 js가 일대일로 대응할 수 있습니다. 어느 것이 저 것인지 알면 어떨까요? 우리의 맞춤 이벤트는 하나씩 해당 매핑 테이블을 우리 자신만이 설정할 수 있고, 그런 다음 이 작업을 수행합니다

var eventTarget = {
  //保存映射
  handlers:{},
  addEvent: function(){
    //处理代码
  },
  fireEvent: function(){
    //触发代码
  },
  removeEvent: function(){
    //移出代码
  }
};

로그인 후 복사

이렇게 매핑 관계를 구성했습니다

handlers = {
  "type1":[
    "fun1",
    "fun2",
    // "..."
  ],
  "type2":[
    "fun1",
    "fun2"
    // "..."
  ]
  //"..."
}
로그인 후 복사

이러한 방식으로 각 유형은 향후 확장을 촉진하기 위해 다양한 처리 기능을 가질 수 있습니다.
다음은 실제 코딩적인 측면, 구체적인 처리코드를 작성하는 부분입니다...

이 아이디어에 대해서는 모두가 이미 매우 명확하다고 생각합니다. 코드를 직접 첨부하겠습니다

//直接量处理js自定义事件
var eventTarget = {
  //保存事件类型,处理函数数组映射
  handlers:{},
  //注册给定类型的事件处理程序,
  //type -> 自定义事件类型, handler -> 自定义事件回调函数
  addEvent: function(type, handler){
    //判断事件处理数组是否有该类型事件
    if(eventTarget.handlers[type] == undefined){
      eventTarget.handlers[type] = [];
    }
    //将处理事件push到事件处理数组里面
    eventTarget.handlers[type].push(handler);
  },
  //触发一个事件
  //event -> 为一个js对象,属性中至少包含type属性,
  //因为类型是必须的,其次可以传一些处理函数需要的其他变量参数。(这也是为什么要传js对象的原因)
  fireEvent: function(event){
    //判断是否存在该事件类型
    if(eventTarget.handlers[event.type] instanceof Array){
      var _handler = eventTarget.handlers[event.type];
      //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件
      for(var i = 0; i < _handler.length; i++){
        //执行触发
        _handler[i](event);
      }
    }
  },
  //注销事件
  //type -> 自定义事件类型, handler -> 自定义事件回调函数
  removeEvent: function(type, handler){
    if(eventTarget.handlers[type] instanceof Array){
      var _handler = eventTarget.handlers[type];
      //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件
      for(var i = 0; i < _handler.length; i++){
        //找出本次需要处理的事件下标
        if(_handler[i] == handler){
          break;
        }
      }
      //删除处理事件
      _handler.splice(i, 1);
    }
  }
};
로그인 후 복사

run을 호출하는 방법입니다

eventTarget.addEvent("eat",function(){
  console.log(123);  //123
});
eventTarget.fireEvent({type: "eat"});
로그인 후 복사

이 방법에는 매핑 테이블을 사용하기 때문에 처리 이벤트를 삭제할 수 없다는 단점이 있으며, 너무 많은 데이터를 매핑 테이블에 직접 저장하는 것은 권장되지 않습니다.

처리 이벤트를 추출하는 또 다른 방법(권장)

function b(){
   console.log(123);
}
eventTarget.addEvent("eat",b);
eventTarget.fireEvent({
  type: "eat"
});                   //123
eventTarget.removeEvent("eat",b);
eventTarget.fireEvent({type: "eat"});  //空
로그인 후 복사

더 많은 매개변수를 전달할 수도 있습니다

eventTarget.fireEvent({
  type: "eat",
  food: "banana"
}); 
function b(data){
   console.log(data.food); //banana
}
로그인 후 복사

요약: 리터럴 메서드에는 약간의 단점이 있습니다. 즉, 실수로 핸들러 함수에서 특정 속성을 null에 할당하면 eventTarget 메서드가 충돌하게 됩니다. 프로토타입을 만드는 것이 좋은 방법이고 조금 더 안전해야 할 것 같습니다.

3. js 맞춤 이벤트를 캡슐화하는 객체 프로토타입

이전 아이디어는 기본적으로 명확하게 설명되어 있으므로 여기에 코드를 직접 첨부하겠습니다. 장단점을 연구하고 더 나은 해결 방법을 찾을 수도 있습니다...

//自定义事件构造函数
function EventTarget(){
  //事件处理程序数组集合
  this.handlers = {};
}
//自定义事件的原型对象
EventTarget.prototype = {
  //设置原型构造函数链
  constructor: EventTarget,
  //注册给定类型的事件处理程序,
  //type -> 自定义事件类型, handler -> 自定义事件回调函数
  addEvent: function(type, handler){
    //判断事件处理数组是否有该类型事件
    if(typeof this.handlers[type] == 'undefined'){
      this.handlers[type] = [];
    }
    //将处理事件push到事件处理数组里面
    this.handlers[type].push(handler);
  },
  //触发一个事件
  //event -> 为一个js对象,属性中至少包含type属性,
  //因为类型是必须的,其次可以传一些处理函数需要的其他变量参数。(这也是为什么要传js对象的原因)
  fireEvent: function(event){
    //模拟真实事件的event
    if(!event.target){
      event.target = this;
    }
    //判断是否存在该事件类型
    if(this.handlers[event.type] instanceof Array){
      var handlers = this.handlers[event.type];
      //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件
      for(var i = 0; i < handlers.length; i++){
        //执行触发
        handlers[i](event);
      }
    }
  },
  //注销事件
  //type -> 自定义事件类型, handler -> 自定义事件回调函数
  removeEvent: function(type, handler){
    //判断是否存在该事件类型
    if(this.handlers[type] instanceof Array){
      var handlers = this.handlers[type];
      //在同一个事件类型下的可能存在多种处理事件
      for(var i = 0; i < handlers.length; i++){
        //找出本次需要处理的事件下标
        if(handlers[i] == handler){
          break;
        }
      }
      //从事件处理数组里面删除
      handlers.splice(i, 1);
    }
  }
};
로그인 후 복사

통화방법

function b(){
  console.log(123);
}

var target = new EventTarget();
target.addEvent("eat", b);

target.fireEvent({
  type: "eat"
});                 //123

로그인 후 복사

프로토타입 방식은 다이렉트 방식과 기능은 동일합니다...

위 내용은 이 글의 전체 내용입니다. 모든 분들의 공부에 도움이 되었으면 좋겠습니다.

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿