웹 프론트엔드 JS 튜토리얼 자바스크립트 이벤트 바인딩 학습포인트_기본지식

자바스크립트 이벤트 바인딩 학습포인트_기본지식

May 16, 2016 pm 03:11 PM

이벤트 바인딩은 두 가지 유형으로 구분됩니다. 하나는 전통적인 이벤트 바인딩(인라인 모델, 스크립트 모델)이고 다른 하나는 최신 이벤트 바인딩(DOM2 수준 모델)입니다. 최신 이벤트 바인딩은 기존 바인딩보다 더 강력하고 편리한 기능을 제공합니다.

1 기존 이벤트 바인딩의 문제점

기존 이벤트 바인딩의 인라인 모델은 논의되지 않으며 거의 ​​사용되지 않습니다. 먼저 스크립트 모델을 살펴보겠습니다. 스크립트 모델은 이벤트 처리 기능에 기능을 할당합니다. 다음과 같은 전통적인 바인딩:

window.onload=function(){
 var box=document.getElementById('box');
 box.onclick = function(){
  alert('Lee');
 };
};



로그인 후 복사

문제 1: 이벤트 처리 함수가 두 개의 이벤트를 트리거합니다

페이지에 두 개 이상의 j가 있고 첫 번째 js는 첫 번째 프로그래머가 개발한 경우 두 번째 js는 두 번째 프로그래머가 개발합니다.

과 같이 첫 번째 window.onload를 덮어씁니다.
window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

로그인 후 복사

이씨님 결과가 방금 출력되었습니다

실제로 이 문제를 해결하는 방법이 있습니다. 다음 두 가지 형태를 살펴보세요.
A:

alert(window.onload);//一开始没有注册window.onload,那么就是null

window.onload=function(){
 alert('Lee');
};

alert(window.onload);//如果已经有window.onload,打印的是函数function

window.onload=function(){
 alert('Mr.lee');
} 

로그인 후 복사

ㄴ:

alert(typeof window.onload);//一开始没有window.onolad,旧版火狐显示undefined,新版显示object,

window.onload=function(){
 alert('Lee');
};

alert(typeof window.onload);//如果已经有window.onload,所有浏览器都会显示function

window.onload=function(){
 alert('Mr.lee');
}

로그인 후 복사

그래서 해결책이 있습니다.

 window.onload=function(){
 alert('Lee');
};

if(typeof window.onload=='function'){
 var saved=null;//保存上一个事件对象
 saved=window.onload;
}

//saved 就是window.onload,saved()相当于window.onload(),但是window.onload()不能执行的
//所以saved()相当于window.onload=function(){}

window.onload=function(){
 if(saved){
  saved();//执行上一个事件 window.onload=function(){}
 }
 alert('Mr.lee'); //执行本事件
}

로그인 후 복사

질문 2: 이벤트 전환기
상자의 ID로 div를 전환하고 내부의 빨간색과 파란색 배경을 직접 전환한 다음 전환하기 전에 다음과 같이 상자를 한 번 팝업합니다.

window.onload=function(){
 var box=document.getElementById('box');
 box.className="red";
 box.onclick=function(){
  alert('Lee'); //只执行了一次
  blue.call(this);//通过匿名函数执行某一函数,那么里面的this就是代表的window,所以可以通过call传递
 };
}

function blue(){
 this.className="blue";
 this.onclick=red;
 
}

function red(){
 this.className="red";
 this.onclick=blue;
}

로그인 후 복사

위 코드에서는 전환 기능을 구현했지만 팝업 상자는 한 번만 실행됩니다.

//添加事件函数
//obj相当于window
//type相当于onload
//fn相当于function(){}
function addEvent(obj,type,fn){
 //用于保存上一个事件
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//保存上一个事件
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}
addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
 // alert('ss');
 //});
 addEvent(box,'click',blue);
});

function red(){
 this.className="red";
 addEvent(box,'click',blue);
}

function blue(){
 this.className="blue";
 addEvent(box,'click',red);
}

//当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
//因为积累了太多的保存的事件
//解决方案,就是用完的事件,就立刻移除掉

로그인 후 복사

위 코드에 따르면 댓글에 오류가 발생했습니다. 해결 방법은 다음과 같습니다.

//添加事件函数
//obj相当于window
//type相当于onload
//fn相当于function(){}
function addEvent(obj,type,fn){
 //用于保存上一个事件
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//保存上一个事件
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}


//当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
//因为积累了太多的保存的事件
//解决方案,就是用完的事件,就立刻移除掉


//移除事件函数
function removeEvent(obj,type){
 if(obj['on'+type]){
  obj['on'+type]=null;
 }
}


addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
 // alert('ss');
 //});
 addEvent(box,'click',blue);
});

function red(){
 this.className="red";
 removeEvent(this,'click');
 addEvent(box,'click',blue);
}

function blue(){
 this.className="blue";
 removeEvent(this,'click');
 addEvent(box,'click',red);
}

로그인 후 복사

두 가지 W3C 이벤트 처리 기능
addEventListener() 및 제거EventListener()
두 가지 W3C 이벤트 처리 함수인 addEventListener()와 RemoveEventListener()가 있습니다.

//W3C에는 추가 이벤트와 삭제 이벤트 두 가지가 있습니다
1. 커버리지 문제 해결

window.addEventListener('load',function(){
 alert('Lee');
},false);

window.addEventListener('load',function(){
 alert('Mr.Lee');
},false);

window.addEventListener('load',function(){
 alert('Mrs.Lee');
},false);

로그인 후 복사

2. 동일한 기능을 차단하는 문제가 해결되었습니다

window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
function init(){
 alert('Lee');
}
로그인 후 복사

3. 이걸 통과해서 해결이 가능할까요
예시 1:

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert(this);
 },false);
},false);

로그인 후 복사

예 2:

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',blue,false);
},false);

function red(){
 this.className="red";
 this.removeEventListener('click',red,false);
 this.addEventListener('click',blue,false);
}

function blue(){
 this.className="blue";
 this.removeEventListener('click',blue,false);
 this.addEventListener('click',red,false);
}

로그인 후 복사

4. 추가 메소드를 덮어쓰나요, 아니면 한 번만 실행할 수 있나요?

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert('Lee');
 },false);
 box.addEventListener('click',blue,false);
},false);
로그인 후 복사

요약하자면 W3C는 이러한 문제를 완벽하게 해결했으며 사용하기 매우 쉽습니다. 그러나 IE8 및 이전 브라우저에서는 이를 지원하지 않습니다. 대신 IE9에서는 이를 완벽하게 지원합니다. 두 가지 이벤트 처리 기능.

W3C에서는 버블링 및 캡처 방법을 설정할 수 있습니다.

W3C 표준을 지원하는 브라우저는 이벤트 추가 시 addEventListener(event,fn,useCapture) 메소드를 사용합니다. 베이스의 세 번째 매개변수인 useCapture는 부울 값으로, 이벤트 캡처 중에 이벤트를 실행할지 여부를 설정하는 데 사용됩니다. 이벤트가 발생하면 담그면 실행됩니다. W3C(IE)와 호환되지 않는 브라우저에서는 AttachEvent() 메서드를 사용합니다. 그러나 IE의 이벤트 모델은 기본적으로 이벤트가 발생할 때, 즉 useCapture가 false일 때 실행됩니다. 이벤트 처리 시 useCapture를 false로 설정하는 것이 더 안전하고, 브라우저 호환성도 확보됩니다.

이벤트 캡처 단계: 이벤트는 최상위 레이블부터 시작하여 이벤트 대상(target)이 캡처될 때까지 아래쪽으로 검색합니다.
이벤트 버블링 단계: 이벤트는 이벤트 대상(target)에서 시작하여 페이지의 최상위 레이블까지 버블링됩니다.
이벤트 확산을 막을 수 있습니다:
W3c에서는 stopPropagation() 메소드를 사용하세요
IE에서는 cancelBubble = true로 설정합니다.

3. IE 이벤트 처리 기능

attachEvent() 및 detachEvent()
IE는 DOM의 메소드와 유사한 두 가지 메소드(attachEvent() 및 detachEvent())를 구현합니다. 두 방법 모두 동일한 매개변수(이벤트 이름 및 기능)를 허용합니다.

이 두 가지 기능 세트를 사용할 때 먼저 차이점에 대해 이야기해 보겠습니다. 1. IE는 캡처를 지원하지 않고 버블링만 지원합니다. 2. IE 추가 이벤트는 중복 기능을 차단할 수 없습니다. 3. IE에서는 이 기능이 대신 창을 가리킵니다. DOM 객체. 4. 기존 이벤트에서 IE는 이벤트 객체를 받아들일 수 없지만 attchEvent를 사용하면 가능하지만 몇 가지 차이점이 있습니다.

1. 취재 문제는 해결됐지만 결과는 이씨, 이씨, 그리고 결국 이씨다

window.attachEvent('onload',function(){
 alert('Lee');
});

window.attachEvent('onload',function(){
 alert('Mr.Lee');
});
window.attachEvent('onload',function(){
 alert('Mrs.Lee');
});

로그인 후 복사

2. 동일 기능을 차단하는 문제가 해결되지 않았습니다.

window.attachEvent('onload',init);
window.attachEvent('onload',init);

function init(){
 alert('Lee');
}

로그인 후 복사

3. 이것이 통과될 수 있습니까? 아니요. 창을 의미합니다. 호출 방식을 사용해야 합니다.

window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.attachEvent('onclick',function(){
  //alert(this===box);
  alert(this===window); //true
 });
});
로그인 후 복사

다음 방법은 window.event.srcElement를 전달하는 것입니다. 코드는 다음과 같습니다.

window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.attachEvent('onclick',blue);
});

function red(){
 var that=window.event.srcElement;
 that.className="red";
 that.detachEvent('onclick',red);
 that.attachEvent('onclick',blue);
}

function blue(){
 var that=window.event.srcElement;
 that.className="blue";
 that.detachEvent('onclick',blue);
 that.attachEvent('onclick',red);
}

로그인 후 복사

4. 추가 메소드를 추가하면 덮어쓰이나요, 아니면 한 번만 실행할 수 있나요?

기존 바인딩에서 IE는 W3C처럼 매개변수 전달을 통해 이벤트 객체를 받아들일 수 없지만, attachmentEvent()를 사용하면 가능합니다.

 window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.onclick=function(evt){ //传统方法IE无法通过参数获取evt
  alert(evt);//undefined
 }
 box.attachEvent('onclick',function(evt){
  alert(evt);//object
  alert(evt.type);//click
  alert(evt.srcElement.tagName);//DIV
  alert(window.event.srcElement.tagName);//DIV
 });
});
로그인 후 복사

크로스 브라우저 호환성

크로스 브라우저 이벤트

function addEvent(obj,type,fn){
 if(obj.addEventListener){
  obj.addEventListener(type,fn,false);
 }else if(obj.attachEvent){
  obj.attachEvent('on'+type,fn);
 }
}
로그인 후 복사

크로스 브라우저 제거 이벤트

function removeEvent(obj,type,fn){
 if(obj.removeEventListener){
  obj.removeEventListener(type,fn,false);
 }else if(obj.detachEvent){
  obj.detachEvent('on'+type,fn);
 }
}
로그인 후 복사

여러 브라우저에서 대상 개체 가져오기

function getTarget(evt){
 if(evt.target){
  return evt.target;
 }else if(window.event.srcElement){
  return window.event.srcElement;
 }
}
로그인 후 복사

调用方式:

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'click',blue);
});


function red(evt){
 var that=getTarget(evt);
 that.className="red";
 removeEvent(that,'click',red);
 addEvent(that,'click',blue);
}

function blue(evt){
 var that=getTarget(evt);
 that.className="blue";
 removeEvent(that,'click',blue);
 addEvent(that,'click',red);
}

로그인 후 복사

四.事件对象的其他补充

relatedTarget事件

w3c中的一个relatedTarget事件。
例如:

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(evt){
  alert(evt.relatedTarget); //得到移入box最近的那个DOM对象
 });
 
 addEvent(box,'mouseout',function(evt){
  alert(evt.relatedTarget); //从box移出最近的那个DOM对象
 });
});
로그인 후 복사

IE提供了两组分别用于移入移出的属性fromElement和toElement,分别对应mouseover和mouseout。

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(){
  alert(window.event.fromElement.tagName); //得到移入box最近的那个DOM对象
 });
 
 addEvent(box,'mouseout',function(){
  alert(window.event.toElement.tagName); //从box移出最近的那个DOM对象
 });
});
로그인 후 복사

PS:fromElement和toElement如果分别对应相反的鼠标事件,没有任何意义。

剩下要做的就是跨浏览器兼容操作:

function getTarget(evt){
 var e=evt || window.event;
 if(e.srcElment){ //IE
  if(e.type=='mouseover'){
   return e.fromElement.tagName;
  }else if(e.type="mouseout"){
   return e.toElement.tagName;
  }
 }else if(e.relatedTarget){ //w3c
  return e.relatedTarget;
 }
}
로그인 후 복사

屏蔽跳转操作

取消事件的默认行为有一种不规范的做法,就是返回false。

link.onclick=function(){
 alert('Lee');
 return false;
}
로그인 후 복사

PS:虽然return false;可以实现这个功能,但是有漏洞。
第一:必须写到最后,这样导致中奖的代码执行后,有可能执行不到return false;
第二:return false 写到最前那么之后的自定义操作就失效了。
所以最好的办法应该是在最前面就阻止默认行为,并且后面的代码还可以执行。

link.onclick=function(evt){
 evt.preventDefault;//w3c,阻止默认行为
 alert('Lee');
}

link.onclick=function(evt){
 window.event.returnValue=false;//IE,阻止默认行为
 alert('Lee');
}

로그인 후 복사

那么跨浏览器的兼容:

function preDef(evt){
 var e=evt || window.event;
 if(e.preventDefault){
  e.preventDefault();
 }else{
  e.returnValue=false;
 }
}
로그인 후 복사

右键菜单contextmenu
兼容:

function preDef(evt){
 var e=evt || window.event;
 if(e.preventDefault){
  e.preventDefault();
 }else{
  e.returnValue=false;
 }
}

addEvent(window,"load",function(){
 var body=document.getElementsByTagName('body')[0];
 addEvent(body,'contextmenu',function(evt){
  preDef(evt);
 })
});

로그인 후 복사

PS:contextmenu事件很常用,这直接导致浏览器兼容性较为稳定。

卸载前事件:beforeunload
这个事件可以帮助在离开本页的时候给出相应的提示,“离开”或者“返回”操作。

addEvent(window,'beforeonload',function(){
 preDef(evt);
});
로그인 후 복사

鼠标滚轮(mousewheel)和DOMMouseScroll
用于获取鼠标上下滚轮的距离

addEvent(document,'mousewheel',function(evt){ //非火狐
 alert(getWD(evt));
});

addEvent(document,'DOMMouseScroll',function(evt){ //火狐
 alert(getWD(evt));
});

function getWD(evt){
 var e=evt|| window.event;
 if(e.wheelDelta){
  return e.wheelDelta;
 }else if(e.detail){ //火狐
  return -evt.detail*30;
 }
}

로그인 후 복사

PS:通过浏览器检测可以确定火狐只执行DOMMouseScroll。

DOMContentLoaded事件和readystatechange事件

DOMContentLoaded事件和readystatechange事件,有关DOM加载方面的事件。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 채팅 명령 및 사용 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

내 자신의 JavaScript 라이브러리를 어떻게 작성하고 게시합니까? 내 자신의 JavaScript 라이브러리를 어떻게 작성하고 게시합니까? Mar 18, 2025 pm 03:12 PM

기사는 JavaScript 라이브러리 작성, 게시 및 유지 관리, 계획, 개발, 테스트, 문서 및 홍보 전략에 중점을 둡니다.

브라우저에서 성능을 위해 JavaScript 코드를 최적화하려면 어떻게해야합니까? 브라우저에서 성능을 위해 JavaScript 코드를 최적화하려면 어떻게해야합니까? Mar 18, 2025 pm 03:14 PM

이 기사는 브라우저에서 JavaScript 성능을 최적화하기위한 전략에 대해 설명하고 실행 시간을 줄이고 페이지로드 속도에 미치는 영향을 최소화하는 데 중점을 둡니다.

프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? 프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? Apr 04, 2025 pm 02:42 PM

프론트 엔드 개발시 프론트 엔드 열지대 티켓 인쇄를위한 자주 묻는 질문과 솔루션, 티켓 인쇄는 일반적인 요구 사항입니다. 그러나 많은 개발자들이 구현하고 있습니다 ...

브라우저 개발자 도구를 사용하여 JavaScript 코드를 효과적으로 디버그하려면 어떻게해야합니까? 브라우저 개발자 도구를 사용하여 JavaScript 코드를 효과적으로 디버그하려면 어떻게해야합니까? Mar 18, 2025 pm 03:16 PM

이 기사는 브라우저 개발자 도구를 사용하여 효과적인 JavaScript 디버깅, 중단 점 설정, 콘솔 사용 및 성능 분석에 중점을 둡니다.

누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? 누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? Apr 04, 2025 am 12:09 AM

기술 및 산업 요구에 따라 Python 및 JavaScript 개발자에 대한 절대 급여는 없습니다. 1. 파이썬은 데이터 과학 및 기계 학습에서 더 많은 비용을 지불 할 수 있습니다. 2. JavaScript는 프론트 엔드 및 풀 스택 개발에 큰 수요가 있으며 급여도 상당합니다. 3. 영향 요인에는 경험, 지리적 위치, 회사 규모 및 특정 기술이 포함됩니다.

소스 맵을 사용하여 조정 된 JavaScript 코드를 디버그하는 방법은 무엇입니까? 소스 맵을 사용하여 조정 된 JavaScript 코드를 디버그하는 방법은 무엇입니까? Mar 18, 2025 pm 03:17 PM

이 기사는 소스 맵을 사용하여 원래 코드에 다시 매핑하여 미니어링 된 JavaScript를 디버그하는 방법을 설명합니다. 소스 맵 활성화, 브레이크 포인트 설정 및 Chrome Devtools 및 Webpack과 같은 도구 사용에 대해 설명합니다.

Console.log 출력 결과의 차이 : 두 통화가 다른 이유는 무엇입니까? Console.log 출력 결과의 차이 : 두 통화가 다른 이유는 무엇입니까? Apr 04, 2025 pm 05:12 PM

Console.log 출력의 차이의 근본 원인에 대한 심층적 인 논의. 이 기사에서는 Console.log 함수의 출력 결과의 차이점을 코드에서 분석하고 그에 따른 이유를 설명합니다. � ...

초보자를위한 타이프 스크립트, 2 부 : 기본 데이터 유형 초보자를위한 타이프 스크립트, 2 부 : 기본 데이터 유형 Mar 19, 2025 am 09:10 AM

엔트리 레벨 타입 스크립트 자습서를 마스터 한 후에는 TypeScript를 지원하고 JavaScript로 컴파일하는 IDE에서 자신의 코드를 작성할 수 있어야합니다. 이 튜토리얼은 TypeScript의 다양한 데이터 유형으로 뛰어납니다. JavaScript에는 NULL, UNDEFINED, BOOLEAN, 번호, 문자열, 기호 (ES6에 의해 소개 됨) 및 객체의 7 가지 데이터 유형이 있습니다. TypeScript는이 기반으로 더 많은 유형을 정의 하며이 튜토리얼은이 모든 튜토리얼을 자세히 다룹니다. 널 데이터 유형 JavaScript와 마찬가지로 Null in TypeScript

See all articles