发表于: 2017-02-16 21:25:48

1 1323


今天完成的事情:

1.今天整理了小日报项目的代码,css文件合并公共样式,js文件合并整理。

2.完成了今天的PPT,学会了jQuery的delegate()方法,知道了冒泡的知识。


明天计划的事情:

1.继续完善日报小网站项目


遇到的问题:

暂无


收获:


1.背景介绍

事件处理程序可以为现代web应用程序提供交互能力,因此许多开发人员会向页面中添加大量的处理程序。但是在JavaScript中,添加到页面中的事件处理程序的数量会直接影响页面的整体运行性能。

原因是因为1.每个函数都是对象,都会占用内存。

2.事先指定所有的事件处理程序会导致DOM的访问次数增加,会延迟整个页面的交互时间。

对“事件处理程序过多”问题的解决方案就是市事件委托(Delegation)。

--JavaScript高级程序设计

今天就主要介绍一下javascript delegate的用法和原理,以及jQuery等框架中delegate的应用。



2.知识剖析

2.1事件绑定

当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点,从而将事件委托给父节点来触发处理函数。

假设有一个 UL 的父节点,包含了很多个 Li 的子节点:


当某个Li被点击的时候需要触发相应的处理事件。我们通常的写法,是为每个Li都添加一些onClick之类的事件监听。


如果这个UL中的Li子元素会频繁地添加或者删除,我们就需要在每次添加Li的时候都调用这个addListeners4Li方法来为每个Li节点添加事件处理函数。这就添加的复杂度和出错的可能性,并且加大了内存的占用

2.2事件代理

更简单的方法是使用事件代理机制,当事件被抛到更上层的父节点的时候,我们通过检查事件的目标对象(target)来判断并获取事件源Li。下面的代码可以完成我们想要的效果:

为父节点添加一个click事件,当子节点被点击的时候,click事件会从子节点开始向上冒泡。父节点捕获到事件之后,通过判断e.target.nodeName来判断是否为我们需要处理的节点。并且通过e.target拿到了被点击的Li节点。从而可以获取到相应的信息,并作处理。


2.3事件冒泡及捕获

DOM2.0模型将事件处理流程分为三个阶段:一、事件捕获阶段,二、事件目标阶段,三、事件起泡阶段。如图:


事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被触发。

2.4事件委托的优点

通过刚才的对比介绍,大家应该能够体会到使用事件委托对于web应用程序带来的几个优点:

  1. 管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件。

  2. 可以方便地动态添加和修改元素,不需要因为元素的改动而修改事件绑定。

  3. JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。


3.常见问题

jQuery中的delegate方法?


4.解决方案

jQuery中的delegate函数

jQuery的delegate的方法需要三个参数,一个选择器,一个事件名称,和事件处理函数。

$("#link-list").delegate("a", "click", function(){

  // "$(this)" is the node that was clicked

  console.log("you clicked a link!",$(this));

});



5.编码实战

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <style>
ul{
width: 200px;
margin: 100px auto;
}
li{
cursor: pointer;
}
</style>
   <script src="https://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<ul id="parent-list">
   <li id="post-1">Item 1</li>
   <li id="post-2">Item 2</li>
   <li id="post-3">Item 3</li>
   <li id="post-4">Item 4</li>
   <li id="post-5">Item 5</li>
   <li id="post-6">Item 6</li>
</ul>

1
<script>
//    创建点击事件监听
function addListeners4Li(li){
li.onclick = function clickHandler(){
alert('点击');
           };
       }
// 获取dom节点,for循环遍历给所有的li添加点击事件监听
window.onload = function(){
var ulNode = document.getElementById("parent-list");
var liNodes = ulNode.getElementsByTagName("Li");
for(var i=0, l = liNodes.length; i < l; i++){
addListeners4Li(liNodes[i]);
           }
       }
</script>

2
<script>

// 获取父节点,并为它添加一个click事件
document.getElementById("parent-list").addEventListener("click",function(e) {
// 检查事件源e.targe是否为Li,target 事件属性可返回事件的目标节点(触发该事件的节点)
if(e.target && e.target.nodeName.toUpperCase() == "LI") {
// 真正的处理过程在这里
console.log("List item ",e.target.id," was clicked!");
}
//    为父节点添加一个click事件,当子节点被点击的时候,click事件会从子节点开始向上冒泡。父节点捕获到事件之后,通过判断e.target.nodeName来判断是否为我们需要处理的节点。并且通过e.target拿到了被点击的Li节点。从而可以获取到相应的信息,并作处理。
});
</script>

3
<script>
//        三个参数,1.选择器(元素名,id或者class);2.事件名称 3.事件处理函数
$("#parent-list").delegate("li", "click", function(){
// "$(this)" 就是被点击的节点
console.log("you clicked a link!",$(this));
   });
</script>

4.
<script>
var delegate = function(client, clientMethod) {
return function() {
return clientMethod.apply(client, arguments);
       }
   }
var ClassA = function() {
var _color = "red";
return {
getColor: function() {
console.log("Color: " + _color);
           },
setColor: function(color) {
_color = color;
           }
       };
   };

var a = new ClassA();
a.getColor();
a.setColor("green");
a.getColor();
console.log("执行代理!");
var d = delegate(a, a.setColor);
d("blue");
console.log("执行完毕!");
a.getColor();
</script>



</body>
</html>


6.扩展思考

什么样的事件可以用事件委托,什么样的事件不可以用呢? 

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。 

值得注意的是,mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。 

不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。


7.参考文献

参考一 :https://www.cnblogs.com/owenChen/archive/2013/02/18/2915521.html

参考二:

http://ithelp.ithome.com.tw/articles/10120565


8.更多思考

在很多框架中都引用了委托这个概念用来指定方法的运行作用域。比较典型的如dojo.hitch(scope,method)和ExtJS的createDelegate(obj,args)。有兴趣的同学可以看一下他们的源代码,主要也是js函数的apply方法来制定执行作用域。


ppt链接:https://ptteng.github.io/PPT/PPT/js-06-EventDelegate.html



返回列表 返回列表
评论

    分享到