事件这块知识点虽然是老生长谈的,但对于我来说多多整理,多多感悟,温故知新,每次看看这块都有不同的收获.(在这里我不会长篇大论,只会挑重点;具体的小伙伴们自行查找)

什么是事件

在编程时系统内发生的动作或者发生的事情.
系统通过它来告诉编程者,在编程者愿意的情况下,编程者一某种方式对它做出回应.

添加事件方式

元素属性

var btn = document.querySelector('button');

btn.onclick = function() {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
} 或者 var btn = document.querySelector('button'); function bgChange() {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
} btn.onclick = bgChange

行内事件

<button onclick="bgChange()">Press me</button>

function bgChange() {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
} 或者 <button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button>

注册事件监听

addEventListener()和removeEventListener();

btn.addEventListener('click', function() {
var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
document.body.style.backgroundColor = rndCol;
}); 或者 btn.removeEventListener('click', bgChange);

优缺点

  • 元素属性
优:
1. 兼容性好
2. 行为的分离
3.便于操作当事对象,因为function是作为on***的属性出现的,可直接用this引用当事对象
缺:
1. 给同一个监听器注册多个处理器,后面的会覆盖前面
btn.onclick=function(){alert('a')};
btn.onclick=function(){alert('b')};
  • 行内事件
优:
1. 兼容性好,是最早的事件处理方法
2. 方便快捷
缺:
1. 代码杂糅
2. 难以管理和效率低下,一个按钮看起来还好,但是如果有一百个按钮呢?得在文件中加上100个属性
3. 文档很难解析
  • 注册事件监听
优:
1. 它允许为事件添加多个单独的处理程序。这对于DHTML库或Mozilla扩展尤其有用,即使使用其他库/扩展也需要很好的工作
2. 它可以让你更好地控制阶段,当听者被激活(捕获与冒泡)
3. 它适用于任何DOM元素,而不仅仅是HTML元素
4. 行为的分离
缺:
兼容性(不过网上有很多成熟的hack);

事件对象

具体请看event详解-https://developer.mozilla.org

  • 在触发DOM上的某个事件时,会在事件处理程序函数中会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息.
var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
alert(event.type); //"click"
}
btn.addEventListener("click", function(event) {
alert(event.type); //"click"
}, false);

event.currentTarget与event.target

事件对象event的target属性始终是事件刚刚发生的元素的引用
  • 例如,你可能有一组16块方格,当它们被点击时就会消失。用e.target总是能准确选择当前操作的东西(方格)并执行操作让它消失,而不是必须以更困难的方式选择它.
var divs = document.querySelectorAll('div');

for (var i = 0; i < divs.length; i++) {
divs[i].onclick = function(e) {
e.target.style.backgroundColor = bgChange();
}
}

阻止默认行为(event.preventDefault())

  • 有时,你会遇到一些情况,你希望事件不执行它的默认行为例如自定义注册表单
var form = document.querySelector('form');
var fname = document.getElementById('fname');
var lname = document.getElementById('lname');
var submit = document.getElementById('submit');
var para = document.querySelector('p');
form.onsubmit = function(e) {
if (fname.value === '' || lname.value === '') {
e.preventDefault();
para.textContent = 'You need to fill in both names!';
}
}

事件冒泡及捕获(event.stopPropagation())

描述事件触发时序问题的术语。
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件。
事件冒泡是自下而上的去触发事件。
绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获。true,事件捕获;false,事件冒泡。默认false,即事件冒泡

事件委托

冒泡还允许我们利用事件委托——这个概念依赖于这样一个事实,如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并将事件监听器气泡的影响设置为每个子节点,而不是每个子节点单独设置事件监听器

如:鼠标放到li上对应的li背景变灰

<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
<li>item6</li>
</ul>
  • 利用事件冒泡实现
$("ul").on("mouseover",function(e){
$(e.target).css("background-color","#ddd").siblings().css("background-color","white");
})
  • 给所有li都绑上事件
$("li").on("mouseover",function(){
$(this).css("background-color","#ddd").siblings().css("background-color","white");
})
代码简洁程度上,两者是相若仿佛的。
前者少了一个遍历所有li节点的操作,所以在性能上肯定是更优的
如果在绑定事件完成后,页面又动态的加载了一些元素
第二种方案,由于绑定事件的时候item7还不存在,所以为了效果,我们还要给它再绑定一次事件.

自定义事件(DOM的事件模拟又称“伪DOM自定义事件”)

  • js原生自定义事件分三个阶段(创造、初始化、触发)

摘自 https://developer.mozilla.org...

(1). 创造

var event = document.createEvent(type);
type:是一个字符串,表示要创建的事件类型。事件类型可能包括是一个字符串,表示要创建的事件类型。
事件类型可能包括"UIEvents", "MouseEvents", "MutationEvents", 或者 "HTMLEvents"

(2) 初始化

event.initEvent('build', true, true);
于初始化通过DocumentEvent接口创建的Event的值。支持三个参数:initEvent(eventName, canBubble,preventDefault)
分别表示事件名称,是否可以冒泡,是否阻止事件的默认操作

(3). 触发

elem.dispatchEvent(event);
参数event表示事件对象,是createEvent()方法返回的创建的Event对象

监听方法

elem.addEventListener('build', function (e) {
// e.target matches elem
}, false);
  • jq自定义dom事件

(1). trigger()

常用模拟
模拟方法操作
$("#btn").trigger("click");
或者
$("#btn").click();
自定义事件
$("#btn").on("myClick", function () {
$("#test").append("<p>我的自定义事件。</p>");
});
$("btn").trigger("myClick");
传递数据
trigger(tpye[,datea]);
第一个参数是要触发的事件类型,
第二个单数是要传递给事件处理函数的附加数据,以数组形式传递。
通常可以通过传递一个参数给回调函数来区别这次事件是代码触发的还是用户触发的
$("#btn").bind("clickCustomize", function (event, message1, message2) { //获取数据
$("#test").append("p" + message1 + message2 + "</p>");
});
$("#btn").trigger("clickCustomize",["我的自定义","事件"]); //传递两个数据
$(“#btn”).trigger(“clickCustomize”,["我的自定义","事件"]); //传递两个数据

(2). triggerHandler();(阻止默认事件)

triggerHandler("lickCustomize");
  • DOM自定义事件优势与劣势:

(1)、优势:

1、自定义事件完全由我们控制触发时机,这就意味着实现了一种 JavaScript 的解耦。我们可以把多个关联但逻辑复杂的操作利用自定义事件的机制灵活地控制好
2、既然绑定也可以解绑,如果不需要了,直接移除绑定事件

(2)、劣势

1、兼容性差,要自己hack(jq除外)

JavaScript疑难杂症系列-事件的更多相关文章

  1. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  2. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  3. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

  4. javascript动画系列第一篇——模拟拖拽

    × 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...

  5. JavaScript 闭包系列二(匿名函数及函数的闭包)

    一. 匿名函数 1. 函数的定义,可分为三种 1) 函数声明方式 function double(x) {     return 2*x; } 2)Function构造函数,把参数列表和函数体都作为字 ...

  6. 深入理解javascript中的事件循环event-loop

    前面的话 本文将详细介绍javascript中的事件循环event-loop 线程 javascript是单线程的语言,也就是说,同一个时间只能做一件事.而这个单线程的特性,与它的用途有关,作为浏览器 ...

  7. JavaScript基础系列

    JavaScript基础系列 JavaScript是一种基于对象和事件驱动的客户端脚本语言. JavaScript的注释 // 单行 /**/ 多行注释 JavaScript变量,函数名和操作符都是区 ...

  8. JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

    本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y) ...

  9. JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

    本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...

随机推荐

  1. Dubbo消费方服务调用过程源码分析

    参考:dubbo消费方服务调用过程源码分析dubbo基于spring的构建分析Dubbo概述--调用过程dubbo 请求调用过程分析dubbo集群容错机制代码分析1dubbo集群容错策略的代码分析2d ...

  2. replace函数更换表中字段的域名

    网站域名更换后,数据库很多链接都是存的绝对路径,这时候需要修改表里字段的路径,使用replace函数更改域名 update 表名 set 字段名 =replace(字段名 ,'旧域名','新域名') ...

  3. 创建全文索引----SQLserver

    1.启动 Microsoft Search 服务 开始菜单-->SQL程序组-->服务管理器-->下拉筐-->Microsoft Search 服务-->启动它. 2. ...

  4. slf4j日志的使用-学习笔记

    maven项目: 一.首先在pom.xml文件中添加maven依赖 这是其中一种: <dependency>     <groupId>org.slf4j</groupI ...

  5. 设置Linux之CentOS7的网络的两种方式动态IP+静态IP

    1 动态IP 参考之前的文章 点击进入 2 静态IP vi /etc/sysconfig/network-scripts/ifcfg-ens33 详情配置如下,上面半部分是我之前的动态IP的设置 静态 ...

  6. 虚拟机Linux下扩展硬盘的方法

    [原文链接]:http://blog.csdn.net/tianlesoftware/article/details/5642883 装虚拟机时空间划小了,于是又加了5G的空间,折腾了半天,挂上去了. ...

  7. shell 脚本中的入参获取与判断

    1.获取shell脚本的入参个数: $# 2.获取shell脚本的第n个入参的字符个数/字符串长度(注意这里的n需要替换为具体的数字,如果这个数字超过实际的入参个数,结果为0): ${#n}

  8. LCD 原理和移植总结【转】

    转自:http://blog.chinaunix.net/uid-22915173-id-329617.html Framebuffer:是linux的framebuffer驱动在内存开辟的一块显存, ...

  9. 17AJAX&JSON

    1. 概念 ASynchronous JavaScript And XML    异步的JavaScript 和 XML1. 异步和同步:客户端和服务器端相互通信的基础上 客户端必须等待服务器端的响应 ...

  10. uestc summer training #3 线段树优化建边

    线段树建边 struct E { int value, modvalue; } a[MAXN << ]; pair<int, int> b[MAXN]; ], r[MAXN & ...