代码要写成别人看不懂的样子(十六)

本篇文章参考书籍《JavaScript设计模式》–张容铭

文章目录

前言

  大家有没有听说过事件委托,你可能没有听说过这个名词,但是你应该使用过事件委托,举个例子,各位都用过 <ul> 标签吧,里面会有很多个 <li> 当我们想要点击某个 <li> 的时候,让它的颜色高亮显示。

  是不是感觉很熟悉,肯定或多或多少都遇到过这样的需求,那我们的这个时候就不能给 <li> 增加点击事件了,翻译数据贼多,这得加到猴年去。

  所以我们的一般做法是给 <ul> 添加点击事件,让 <li> 的事件冒泡到 <ul> 上就可以了。

委托模式

   多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求

  前面的例子我们实现一下:

ul.onclick = function(e) {
    
    
	var e = e || window.event,
		tar = e.target || e.srcElement;
	if(tar.nodeName.toLowerCase() === 'li') {
    
    
		tar.style.backgroundColor = 'grey';
	}
}

  事件委托的原理很简单,但是实现的功能可不止上面这一个,有的时候能帮我“预言未来”。

  说的有点玄乎哈,其实呢是处理当前不存在的页面,比如我们会在未来的某个时刻添加某个元素,那想要给未来的元素绑定事件,现在的技术实现起来还是有点困难的,不过事件委托可以巧妙的把绑定事件这件事委托给现有的父元素,便可以实现我们需要的功能了。

<div id="article">
	<p>Hello World</p>
</div>

  上面给 p 标签增加点击事件很容,到那时如果将来要在 Hello World 下面再加一段话,就得转化一下思路,将事件绑定在父元素 div 上,比如:

var article = focument.getElementById('article');
article.onclick = fucntion() {
    
    
	var e = e || window.event,
		tar = e.target || e.srcElement;
	if(tar.nodeName.tolowerCase() === 'p') {
    
    
		tar.innerHTML = '修改内容!';
	}
}
var p = document.createElement('p');
p.innerHTML = '新增一段内容';
article.appendChild(p);

  这还没完,委托模式还可以处理一些内存泄漏问题,比如我们的老相识 IE ,由于它引用计数式垃圾回收机制,使得那些对 Dom 元素的引用没有显性清楚的数据就会留在内存中。除非关闭浏览器,否则无法删除,比如:

扫描二维码关注公众号,回复: 13049113 查看本文章
<div id="btn_container">
	<button id="btn">demo</button>
</div>
var g = function(id) {
    
    return document.getElementById(id)}
g('btn').onclick = function() {
    
    
	g('btn_container').innerHTML = '触发了事件';
}

  为 id 为 btn 的元素绑定点击事件,在触发时,在其父元素中重置内容,这样将会将按钮自身覆盖掉,然而 g 变量保存的元素绑定的 click 事件没有清除,所以这个事件就会泄漏到内存中。为了解决这一问题,我们可以在父元素设置内容前显性的清除事件事件,比如:

g('btn').onclick = function() {
    
    
	g('btn') = null;
	g('btn_container').innerHTML = '触发了事件';
}

  但是 g(‘btn’) = null; 这个清除事件语句在一些标准浏览器中是不需要的,因为他们采用标记清除方式管理自身内存。所以更好的办法就是委托模式了。

g('btn_container').onclick = function(e) {
    
    
	//获取触发事件元素
	var target = e && e.target || window.event.srcElement;
	//判断事件触发元素是否是 id 为 btn 的元素
	if(target.id === 'btn') {
    
    
		//重置父元素内容
		g('btn_container').innerHTML = '触发了事件';
	}
}

  事件委托的应用还不止如此,再比如我们向后端发送一些请求时,如果有多个模块都需要发送请求,通常做法是下面:

$.get('./deal.php?g=banner', function(res) {
    
    
	//处理banner模块逻辑
})
$.get('./deal.php?g=aside', function(res) {
    
    
	//处理aside模块逻辑
})
$.get('./deal.php?g=article', function(res) {
    
    
	//处理article模块逻辑
})
$.get('./deal.php?g=member', function(res) {
    
    
	//处理member模块逻辑
})
$.get('./deal.php?g=message', function(res) {
    
    
	//处理message模块逻辑
})

  这样做我们会向服务器发送 5 次请求,既是对资源的浪费,又会造成漫长的等待,然而更好的方式是将这些请求打包,委托另外一个对象发送,当得到响应数据时,再通过委托对象拆包数据分发给各模块。比如:

var Deal = {
    
    
	banner: function() {
    
    
		//处理banner模块逻辑
	},
	aside: function() {
    
    
		//处理aside模块逻辑
	},
	article: function() {
    
    
		//处理article模块逻辑
	},
	member: function() {
    
    
		//处理member模块逻辑
	},
	message: function() {
    
    
		//处理message模块逻辑
	}
}
$.get('./deal.php?', function(res) {
    
    
	//数据拆包分发
	for(var i in res) {
    
    
		Deal[i] && Deal[i](res[i]);
	}
});

  这样我们通过一个请求,将 5 次业务一次性完成,节省时间,又节约开销。



猜你喜欢

转载自blog.csdn.net/EcbJS/article/details/110930552