首頁 > web前端 > js教程 > JavaScript 事件綁定及深入_基礎知識

JavaScript 事件綁定及深入_基礎知識

WBOY
發布: 2016-05-16 16:04:27
原創
1114 人瀏覽過

事件綁定分為兩種:

一種是傳統事件綁定(內聯模型/腳本模型);上一章內容;
一種是現代事件綁定(DOM2級模型);現代事件綁定在傳統事件綁定基礎上提供了更強大的功能;
一 傳統事件綁定的問題

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

// 脚本模型将一个函数赋值给一个事件处理函数;

  var box = document.getElementById('box');  // 获取元素;

  box.onclick = function(){          // 元素点击触发事件;

    alert('Lee');

  }

 

// 问题一:一个事件处理函数触发两次事件;

  window.onload = function(){         // 第一组程序;

    alert('Lee');

  }

  window.onload = function(){         // 第二组程序;

    alert('Mr.Lee');

  }

  // PS:当两组程序同时执行的时候,后面一个会把前面一个完全覆盖;

  // 导致前面的window.onload完全失效了;

// 解决方案:

  window.onload = function(){         // 第一组事件处理程序,会被覆盖;

    alert('Lee');

  }

  if(typeof window.onload == 'function'){   // 判断之前是否有window.onload;

    var saved = null;            // 创建一个保存器;

    saved = window.onload;          // 把之前的window.onload保存起来;

  }

  window.onload = function(){         // 下一个要执行的事件;

    // saved()=window.onload = function

    if(saved)saved();            // 判断之前是否有事件,如果有则先执行之前保存的事件;

    alert('Mr.Lee');             // 执行本事件的代码;

  }

登入後複製

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// 问题二:事件切换器

  box.onclick = boBlue;             // 第一次执行toBlue();

  function toRed(){

    this.className = 'red';

    this.onclick = toBlue;          // 第三次执行roBlue(),然后来回切换;

  }

  function toBlue(){

    this.className = 'blue';

    this.onclick = toRed;          // 第二次执行toRed();

  }

  // 这个切换器在扩展的时候,会出现一些问题:

  1.如果增加一个执行函数,那么会被覆盖;

  box.onclick = toAlert;            // 被增加的函数;

  box.onclick = toBlue;            // toAlert被覆盖了;

 

  2.如果解决覆盖问题,就必须包含同时执行;

  box.onclick = function(){          // 包含进去,但可读性降低;

    toAlert();                // 第一次不会被覆盖,但第二次又被覆盖;

    toBlue.call(this);            // 还必须把this传递到切换器里;

  }

登入後複製

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

// 综上三个问题:覆盖问题/可读性问题/this传递为题;

// 我们创建一个自定义事件处理函数;

  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);           // 执行函数,把this传递进去;

    }

  }

  addEvent(window,'load',function(){

    alert('Lee');              // 可以执行;

  });

  addEvent(window.'load',function(){

    alert('Mr.Lee');            // 可以执行;

  })

 

// 用自定义事件函数注册到切换器上查看效果:

  addEvent(window,'load',function(){

    var box = document.getElementById('box');

    addEvent(box,'click',toBlue);

  });

  function toRed(){

    this.className = 'red';

    addEvent(this,'click',toBlue);

  }

  function toBlue(){

    this.className = 'blue';

    addEvent(this,'click',toRed);

登入後複製

二 W3C事件處理函數
// "DOM2級事件"定義了兩個方法,用於新增事件和刪除事件的處理程序:addEventListener()和removeEventListener();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

// 所有DOM节点中都包含这两个方法,并且它们都接收3个参数:事件名/函数/冒泡或捕获的布尔值(true表示捕获,false表示冒泡);

  window.addEventListener('load',function(){

    alert('Lee');

  },false);

  window.addEventListener('load',function(){

    alert('Mr.Lee');

  },false);

  // PS:W3C的事件绑定好处:1.不需要自定义了;2.可以屏蔽相同的函数;3.可以设置冒泡和捕获;

  window.addEventListener('load',init,false);    // 第一次执行了;

  window.addEventListener('load',init,false);    // 第二次被屏蔽了;

  function init(){

    alert('Lee');

  }

 

// 事件切换器

  window.addEventListener('load',function(){

    var box = document.getElementById('box');

    box.addEventListener('click',function(){    // 不会被覆盖/误删;

      alert('Lee');

    },false);

    box.addEventListener('click',toBlue,false);  // 引入切换;

  },false);

 

  function toRed(){

    this.className = 'red';

    this.removeEventListener('click',toRed,false); // 移除事件处理函数;

    this.addEventListener('click',toBlue,false);  // 添加需要切换的事件处理函数;

  }

 

  function toBlue(){

    this.className = 'blue';

    this.removeEventListener('click',toBlue,false);

    this.addEventListener('click',toRed,false);

  }

 

// 设置冒泡和捕获阶段

  document.addEventListener('click',function(){

    alert('document');

  },true);                    // 设置为捕获;

 

  document.addEventListener('click',function(){

    alert('Lee');

  },false);                    // 设置为冒泡;

登入後複製

三 IE事件處理函數
// IE中實作了兩個與DOM類似的方法:attachEvent()和detachEvent();

// 這兩個方法接收相同的參數:事件名稱和函數;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

// 在使用这两组函数的时候,区别:

// 1.IE不支持捕获,只支持冒泡;

// 2.IE添加事件不能屏蔽重复的函数;

// 3.IE中的this指向的是window而不是DOM对象;

// 4.在传统事件上,IE是无法接受到event对象的;但使用了attachEvent()却可以;

  window.attachEvent('onload',function(){

    var box = document.getElementById('box');

    box.attachEvent('onclick',toBlue);

  });

 

  function toRed(){

    var that = window.event.srcElement;

    that.className = 'red';

    that.detachEvent('onclick',toRed);

    that.attachEvent('onclick',toBlue);

  }

 

  function toBlue(){

    var that = window.event.srcElement;

    that.className = 'blue';

    that.detachEvent('onclick',toBlue);

    that.attachEvent('onclick',toRed);

  }

  // PS:IE不支持捕获;

  // IE不能屏蔽;

  // IE不能传递this,可以call过去;

 

// 在传统绑定上,IE是无法像W3C那样通过传参接受event对象;但如果使用了attachEvent()却可以;

  box.onclick = function(evt){

    alert(evt);                // undefined;

  }

 

  box.attachEvent('onclick',function(evt){

    alert(evt);                // object;

    alert(evt.type);              // click;

  });

 

// 兼容IE和W3C的事件切换器函数;

  function addEvent(obj,type,fn){        // 添加事件处理程序兼容;

    if(obj.addEventListener){

      obj.addEventListener(type,fn);

    }else if(obj.attachEvent){

      obj.attachEvent('on'+type,fn);

    }

  }

 

  function removeEvent(obj,type,fn){      // 移除事件处理程序兼容;

    if(obj.removeEventListener){

      obj.removeEventListener(type,fn);

    }esle if(obj.detachEvent){

      obj.detachEvent('on'+type,fn);

    }

  }

 

  function getTarget(evt){           // 得到事件目标;

    if(evt.target){

      return evt.target;

    }else if(window.event.srcEleemnt){

      return window.event.srcElement;

    }

  }

登入後複製

四 事件物件補充

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

1.relatedTarget

// 这个属性可以在mouseover和mouseout事件中获取从哪里移入和从哪里移出的DOM对象;

  box.onmouseover = function(evt){      // 鼠标移入box;

    alert(evt.relatedTarget);        // 获取移入box之前的那个元素;

  }

  box.onmouseout = function(evt){       // 鼠标移出box;

    alert(evt.relatedTarget);        // 获取移出box之后到的那个元素;

  }

 

// IE提供了两组与之对应的属性:fromElement和toElement;

// 兼容函数

  function getEarget(evt){

    var e = evt || window.event;      // 得到事件对象;

    if(e.srcElement){            // 如果支持srcElement,表示IE;

      if(e.type == 'mouseover'){     // 如果是over事件;

        return e.fromeElement;     // 就使用from;

      }else if(e.type == 'mouseout'){   // 如果是out;

        return e.toElement;       // 就使用to;

      }

    }else if(e.relatedTarget){       // 如果支持relatedTarget,表示W3C;

      return e.relatedTarget;

    }

  }

登入後複製

2.阻止事件的預設行為

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// 一个超链接的默认行为就点击然后跳转到指定的页面;

// 那么阻止默认行为就可以屏蔽跳转的这种操作,而实现自定义操作;

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

  link.onclick = function(){

    alert('Lee');           

    return false;              // 直接返回false,就不会跳转了;

  }

  // PS:虽然return false;可以实现这个功能,但有漏洞;

  // 第一:代码必须写到最后,这样导致中间的代码执行后,有可能执行不到return false;

  // 第二:return false写到最前那么之后的自定义操作就失败了;

  // 解决方案:在最前面就阻止默认行为,并且后面还能执行代码;

  function preDef(evt){            // 跨浏览器兼容阻止默认行为;

    var e = evt || window.event;

    if(e.preventDefault){

      e.preventDefault();         // W3C,阻止默认行为;

    }else{

      e.returnValue = false;        // IE,阻止默认行为;

    }

  }

登入後複製

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

3.上下文菜单事件contextmenu

// 当我们右击网页的时候,会自动出现windows自带的菜单;

// 那么我们可以使用contextmenu事件来修改我们指定的菜单;但前提是把右击的默认行为取消;

  addEvent(window,'load',function(){

    var text = docuemnt.getElementById('text');

    addEvent(text,'contextmenu',function(evt){    // 添加右键菜单事件处理程序;

      var e = evt || window.event;

      preDef(e);                  // 阻止默认行为函数;

      var menu = document.getElementById('menu');  // 找到自定义的menu对象;

      menu.style.left = e.clientX+'px';       // 确定自定义menu在屏幕上的位置;

      menu.style.top = e.clientX+'px';

      menu.style.visibility = 'visible';      // 设置自定义menu的属性为可见;

      addEvent(document,'click',function(){     // 给document添加单击事件处理程序;

        docuemnt.getElementById('myMenu').style.visibility = 'hidden'//将自定义的menu隐藏;

      });

    });

  });

登入後複製

4.卸載前事件beforeunload

1

2

3

4

5

6

7

// 这个事件可以帮助在离开本页的时候给出相应的提示;"离开"或"返回"操作;

  addEvent(window.'beforeunload',function(evt){

    var evt = event || window.event;

    var message = '是否离开此页?';

    evt.returnValue = message;

    return message;

  });

登入後複製

5.滑鼠滾輪(mousewheel)和DOMMouseScroll

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// 用于获取鼠标上下滚轮的距离;

  addEvent(docuemnt,'mousewheel',function(evt){    // 非Firefox;

    alert(getWD(evt));

  });

  addEvent(docuemnt,'DOMMouseScroll',function(evt){  // Firefox;

    alert(getWD(evt));

  });

  

  function getWD(evt){

    var e = evt || window.event;

    if(e.wheelDelta){                // mousewheel事件的滚动值保存在wheelDelta里;

      return e.wheelDelta;

    }else if(e.detail){               // DOMMouseScroll事件的滚动值保存在detail里;

      return -evt.detail*30;            // 保持计算的统一;

    }

  }

登入後複製
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板