热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

JavaScript事件绑定及深入

这篇文章主要介绍了JavaScript事件绑定及深入,需要的朋友可以参考下

事件绑定分为两种:

一种是传统事件绑定(内联模型/脚本模型);上一章内容;
一种是现代事件绑定(DOM2级模型);现代事件绑定在传统事件绑定基础上提供了更强大的功能;
一 传统事件绑定的问题

// 脚本模型将一个函数赋值给一个事件处理函数;
  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');             // 执行本事件的代码;
  }
// 问题二:事件切换器
  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传递到切换器里;
  }
// 综上三个问题:覆盖问题/可读性问题/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();

// 所有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.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.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.阻止事件的默认行为

// 一个超链接的默认行为就点击然后跳转到指定的页面;
// 那么阻止默认行为就可以屏蔽跳转的这种操作,而实现自定义操作;
// 取消事件默认行为还有一种不规范的做法,就是返回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,阻止默认行为;
    }
  }
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

// 这个事件可以帮助在离开本页的时候给出相应的提示;"离开"或"返回"操作;
  addEvent(window.'beforeunload',function(evt){
    var evt = event || window.event;
    var message = '是否离开此页?';
    evt.returnValue = message;
    return message;
  });

5.鼠标滚轮(mousewheel)和DOMMouseScroll

// 用于获取鼠标上下滚轮的距离;
  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;            // 保持计算的统一;
    }
  }

推荐阅读
  • 本文探讨了如何利用HTML5和JavaScript在浏览器中进行本地文件的读取和写入操作,并介绍了获取本地文件路径的方法。HTML5提供了一系列API,使得这些操作变得更加简便和安全。 ... [详细]
  • 一个登陆界面
    预览截图html部分123456789101112用户登入1314邮箱名称邮箱为空15密码密码为空16登 ... [详细]
  • 本文详细介绍了在Linux环境下如何有效地管理任务,包括撤销操作、挂起与恢复任务、终止后台程序以及取消定时任务的方法。这些技巧对于提高日常工作效率和系统维护至关重要。 ... [详细]
  • Microsoft即将发布WPF/E的CTP(Community Technology Preview)和SDK,标志着RIA(Rich Internet Application)技术的新里程碑。更多详情及下载链接请参见MSDN官方页面。 ... [详细]
  • 本文探讨了如何为Web浏览器(如Firefox)添加全局热键(例如媒体控制键),并详细说明了实现这一功能所需的步骤,包括可能需要的Firefox扩展和Greasemonkey脚本。 ... [详细]
  • 在使用Firefox浏览器打开本地HTML文件时,尝试调用Canvas的drawImage方法可能会遇到NS_ERROR_NOT_AVAILABLE错误。本文探讨了这一问题的原因及解决方案。 ... [详细]
  • 本文探讨了如何通过WebBrowser控件在用户点击输入框时自动显示图片验证码。该过程可能涉及JavaScript事件的触发与响应。 ... [详细]
  • 探讨GET与POST请求数据传输的最大容量
    在Web开发领域,GET和POST是最常见的两种数据传输方法。本文将深入探讨这两种请求方式在不同环境下的数据传输能力及其限制。 ... [详细]
  • 本文介绍了如何利用Selenium和Python通过执行JavaScript代码来控制网页中的滚动条,包括垂直和水平滚动条的控制,以及特定元素的聚焦技术。 ... [详细]
  • 利用CSS3和React实现数字滚动动画组件
    在前端开发中,数字滚动动画是一个常见的需求。本文将详细介绍如何使用CSS3和React构建一个数字滚动动画组件,包括组件的代码实现和样式设计。如果您对HTML版本感兴趣,欢迎留言获取。 ... [详细]
  • 本文提供了针对Windows 7操作系统中,使用浏览器时出现电脑卡死问题的有效解决方案,包括检查硬件加速设置、安全模式下的故障排查以及利用崩溃日志进行深入分析的方法。 ... [详细]
  • 本实验利用xmlspy2013和firefox工具,探讨如何编写和验证基于DTD的XML文档。实验包括分析XML实例以创建相应的DTD文档,并通过编写有效的XML文档来验证DTD的有效性。 ... [详细]
  • 网页中正确显示英语音标的方法与实例
    在开发教育类网站时,经常遇到的一个问题是如何在网页上正确显示英语音标,以及为何某些情况下音标会显示为乱码。本文将探讨这些问题的成因及解决方案。 ... [详细]
  • Exploring the issue where the onScroll event does not correctly capture clientX and clientY values across different browsers. ... [详细]
  • 本文详细介绍了在Ubuntu 7.10操作系统上安装多种常用软件的方法,包括RAR压缩工具、即时通讯软件Pidgin、办公软件永中Office 2007试用版、多线程下载软件MultiGet及d4x、FTP客户端gFTP与FireFTP插件,以及P2P下载工具aMule。每部分都提供了具体的安装步骤和配置方法。 ... [详细]
author-avatar
秋天的紫丁香
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有