javascript 事件相关使用总结01

这里总结一下js事件相关的经验。

addEventLinstener()介绍

注册事件最基础的函数是这个
target.addEventListener(type, listener[, useCapture]);
这个有一些可以注意的地方
1.第二个参数它需要的是一个实现了EventListener接口的对象。但是也可以传递一个函数,最常见的就是传一个匿名函数
2.第三个useCapture参数指明是事件传递是自下向上冒泡,还是从上到下传递。
 
先总结一下第一点的问题
最常见的用法
var btn01 = document.getElementById("btn01");
btn01.addEventListener("click", function() {
console.log(this);
});

或者

function func() {console.log("func");}

var btn01 = document.getElementById("btn01");
btn01.addEventListener("click", func);
前一种是传递匿名函数,后一种是函数名。有什么区别?
 
匿名函数无法用removeEventListener移出事件的注册。后者可以
var btn01 = document.getElementById("btn01");
btn01.addEventListener("click", func);
btn01.removeEventListener("click", func);

注意:需要移出的注册事件,addEventListener和removeEventListener的参数必须一样。

 
用匿名函数方式,每个匿名函数被看作一个独立的函数,即便匿名函数内容一样。
在下面这种情况下它比函数名方式更加占内存。
//对所有div注册一个点击事件
var divs = document.getElementsByTagName("div");
for (var i=0; i<divs.length; i++) {
divs[i].addEventListener("click", function() {
func();
});
}
 
另外一个很重要的地方就是匿名函数方式每次注册都是独立的。例如
btn01.addEventListener("click", function() {
console.log(this);
});
btn01.addEventListener("click", function() {
console.log(this);
});

这样点击事件被看作两个有两个回调注册,会执行两次。

 
而后者函数名方式,则被看做是同样的回调注册。只注册一次,回调函数代码也只执行一次。
btn01.addEventListener("click", c);
btn01.addEventListener("click", c);

与jquery相关的问题。

如果用jquery注册的话,不管是不是匿名函数,每次注册都是生效的。例如
$(document).ready(function() {
$("#btn01").click(func);
$("#btn01").click(func);
});

func函数会执行两次。这个是和addEventListener方式不一样的地方之一。用jquery的时候这个问题还是很容易出现的。

 

EventListener接口的用法

只需要一个有handleEvent方法的对象即可。例如
var events = {
handleEvent : function(event) {
switch (event.type) {
case 'click':
//......
break;
case 'dbclick':
//......
break;
default:
break;
}
}
}
btn01.addEventListener("click", events, false);
btn01.addEventListener("dblclick", events, false);
这样点击和双击事件都会执行handleEvent方法,再根据event.type类型做不同的分支。
这种做法的好处就是更加面向对象一点,需要处理的数据可以由同一的对象管理。例如以下一个简单的例子
 function BtnHandler(element) {
this.element = element;
this.name = "button"; this.handleEvent = function(event) {
switch(event.type) {
case 'click':
this.clickHandler(event);
break;
case 'dblclick':
this.dblclickHandler(event);
break;
}
};
this.clickHandler = function(event) {
console.log("clickHandler");
}
this.dblclickHandler = function(event) {
console.log("dblclickHandler");
} element.addEventListener('click', this, false);
element.addEventListener('dblclick', this, false);
}
//注册
BtnHandler(btn01);

第二个点useCapture参数。

1.true为Capture方式,由外向里顺序执行。
2.false为Bubbling冒泡方式,由里向外冒泡。默认它是false
 
事件传递机制不多说了,有许多文章可以参考。 这里说说与它相关的有两个标准的接口。
stopPropagation和preventDefault
stopPropagation很简单就是阻止事件继续传递。
而preventDefault原本是用来标记事件被取消了的。但是注意preventDefault调用后事件仍然会继续传递。
我发现的preventDefault唯一的用处就在移动设备上。有一些移动设备会出现“点穿现象”,
例如一个div层在下面,上面再盖一个div层(只是位置上覆盖,DOM树结构不是上下级关系,排除事件冒泡的影响)。上层DIV响应点击事件后如果执行力从DOM树中移出的操作,这种情况下下面的DIV也会响应到click事件。
这个时候使用event.preventDefault()便可以避免这种“点穿影响”。但是注意preventDefault会像它名字一样阻止浏览器的默认行为。例如按钮的点击特效等。
 
旧方式注册事件注意点
1.直接html写的。
<button id="btn01" onclick="func();">btn01</button>
function func() {
console.log(this); //这里的this是全局的window
}

这种使用的比较少,但是要注意它的回调函数里面没有绑定this。也就是它回调里面的this指向全局的window

 
2. 属性方式的写法
btn01.onclick = function() {}; 
这种写法在一些浏览器上可能不支持。并且它只能为某一个事件添加一个回调。
btn01.onclick = func01;
btn01.onclick = func02;

这样的click事件只能注册最后一个回调函数。

ready onload介绍 

onload的作用是指元素装载完成后的回调,一般用在body上和image上。并不是所有的元素都有这个回调,支持的元素有以下。
<body>, <frame>, <frameset>, <iframe>, <img>, <link>, <script>
例如
<body onload="load();"><img onload="func();" src="xx" /> 
js代码中的一些内置对象也有此回调。例如image, window对象。例如
var div01 = document.getElementById("div01");

var image = new Image();

image.onload = function() {

    console.log("img onload");

};

image.src = "1.jpg";

div01.appendChild(image);
一个要点是body上注册的onload事件会等待所有的资源加载完后执行。单个img里面的则是自己加载完就执行。
我们使用的时候往往用jquery的ready。这个更好用。
$(document).ready(function() {

}
有什么不同呢,
1.body onload会等待图片,静态文件等都加载完成之后执行。ready只是等dom树和js装载完(包含自执行的js代码执行完成)。
自执行的代码例子如下
<script>

(function() {

    //......这里就是自执行的代码了,也就是一装载就开始执行。

})();

</script>

如果有耗时操作的话。例如下例。ready也是会等到这些执行完成后再响应。这一点需要注意一下。

(function() {

    var sum = 0;

    for (var i=0; i< 1000000; i++) {

        sum += i;

    }

    console.log(sum);

})();
注意:不能用setTimeout或者异步代码来模拟耗时操作,概念不一样。
 
所以ready会比onload更早响应,并且使用也更加合理。我们只需要js和dom完了就可以写js代码逻辑来,不必要非要等图片等加载完。
 
2.onload注册多个回调不方便。用jquery的ready就不一样了(前面也提到过用jquery注册的,那怕是相同的函数也都会被单独执行)。
用onload多个回调函数写法这样,不是很方便。
<body onload="load();load2();load3();">
3.另外body的onload和jquery的ready不能同时使用,同时注册onload会不响应。
如果需要同时用到body的onload和ready的回调时机可以使用window的onload取代。它的响应时机跟body的onload差不多。并且window和body的onload同时注册body的也不响应。
(function() {

    window.onload = function() {

        console.log("window.onload");

    };

})();

或者

$(document).ready(function() {

    $(window).load(function() {

        console.log("jquery window load");

    });

}); 

事件委托处理 

如果有动态的添加的dom元素或者说有许多相同的元素需要绑定同样的事件。则用事件委托则方便许多。
例如一个div里面动态添加了许多个button.
$(document).ready(function() {

    var div01 = document.getElementById("div01");
for (var i=0; i<10; i++) {
var btn = document.createElement("button");
btn.innerHTML = "btn" + i;
btn.addEventListener("click", function() {
//.......
});
div01.appendChild(btn);
}
});
如果添加button的代码是某个程序运行中执行的。则上述方式有两个问题,第一注册事件代码需要添加按钮后执行,并且添加的内容可能根据不同情况而不一样,
这样可能会导致一些代码的重复而变得不好维护。
 
第二,更加占用内存。尤其如果使用的是匿名函数的方式注册的话。
 
事件委托就是利用事件冒泡,将事件注册到父元素上,这样就子元素不管是不是动态添加的,或者多少个都可以响应到。如果需要用到事件源则可以利用事件的event.target属性分辨出来那个元素。
div01.addEventListener("click", function(event) {
console.log(event.target.innerHTML);
});
这个有jqeury包装好的方法可用live()和delegate()
live是将事件绑定在DOM的根节点上。所以在任意时候使用
$("button").live("click", func);
delegate是将事件绑定在特定的父节点上所以使用的时候要指定父节点
$("div").delegate("button", "click", func);

javascript 事件相关使用总结01的更多相关文章

  1. javascript 事件相关

    1.添加事件 >基本注册方式 <button id="info">click me!</button> var span = document.get ...

  2. 重温javascript事件机制

    以前用过一段时间的jquery感觉太方便,太强大了,各种动画效果,dom事件.创建节点.遍历.控件及UI库,应有尽有:开发文档也很多,网上讨论的问题更是甚多,种种迹象表明jquery是一个出色的jav ...

  3. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

  4. JavaScript事件代理和委托(Delegation)

    JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...

  5. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  6. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  7. JavaScript事件对象与事件处理程序

    在学习之前建议请看一下事件流.事件冒泡.事件捕获 一.事件对象 事件对象:在DOM触发事件时,会产生一个事件对象event,这个事件对象包含着所有与事件相关的信息.既然event是事件对象,那么它必然 ...

  8. JavaScript事件流原理解析

    一.为什么会有这一篇的文章 国庆前几天由于任务比较重,要赶在国庆前把一个进度的任务开发完成,所以也就有点赶,但是却遇到了一个比较奇怪的Bug,导致了任务比预计的延迟了几个小时,对此深表遗憾,所以利用国 ...

  9. Javascript事件模型系列(四)我所理解的javascript自定义事件

    被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...

随机推荐

  1. vue 路由传参 、接收参数

    传参组件 一. <router-link :to='"/main/course?navName=" +item.columnName + "&id=&quo ...

  2. 12.2.0.1 restart环境执行root.sh 报 CLSRSC-400 错误

    问题描述: 在LINUX 7.5 的环境上安装12.2.0.1 Restart Grid环境,执行root.sh  报 CLSRSC-400 错误 错误如下: 解决办法: 1. 参考(文档ID 136 ...

  3. golang笔记

    ----------- golang打包和部署到centos7. 参考:https://blog.csdn.net/qq_33230584/article/details/81536572

  4. org.elasticsearch.script.Script使用

    org.elasticsearch.script.Script使用 public Map<String, Object> builderMapPackage(PageBean pageBe ...

  5. Dubbo---初识

    1.概述 1.1 Dubbo是一款高性能.轻量级的java RPC框架: 1.2 Dubbo提供的功能: 面向接口的远程调用: 智能容错.负载均衡: 服务注册.发现: 1.3 Dubbo架构 Prov ...

  6. 基于JQuery easyui,gson的批量新增/修改和删除-servlet版

    最近项目需要用到在页面进行批量操作,做了一些这方面的学习,参照网上的资料写了个小例子,记录一下: 准备 引入gson-2.6.2.jar,这里使用gson而不使用json-lib,原因是json-li ...

  7. C# 获取类名

    1.获取C#类中类名 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name; 2.获取C#类中类名(包含命名空间) Sy ...

  8. 【OpenCV-Python】-图像阀值

    参考:Opencv官方教程 1.简单阀值 cv2.threshold , cv2.adaptiveThreshold当像素值高于阀值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一 ...

  9. Java基础28-继承

    /* 继承的概述: 1.提高了代码复用性,简化了代码 2.让类与类之间产生了继承关系,才有了后面的多态特性的存在 注意:千万不要为了获取其他类的功能简化代码,而建立继承关系,必须要类与类之间存在继承关 ...

  10. OC SEL (@selector) 原理及使用总结(转)

    SEL 类成员方法的指针 可以理解 @selector()就是取类方法的编号,他的行为基本可以等同C语言的中函数指针,只不过C语言中,可以把函数名直接赋给一个函数指针,而Object-C的类不能直接应 ...