在实际开发中,经常需要为Dom元素绑定事件,如果页面上有4个li元素,点击对应的li,弹出对应的li内容,怎么做呢?是不是很简单?

大多数人的做法都是:获取元素,绑定事件

     <ul>
<li>跟着ghostwu学习javascript设计模式的应用1</li>
<li>跟着ghostwu学习javascript设计模式的应用2</li>
<li>跟着ghostwu学习javascript设计模式的应用3</li>
<li>跟着ghostwu学习javascript设计模式的应用4</li>
</ul>
<script>
var aLi = document.querySelectorAll( "li" );
aLi.forEach(( ele, ind ) => {
ele.addEventListener( "click", ()=> {
alert( ele.innerHTML );
} );
});
</script>

如果页面上有1w个元素, 甚至10w个元素呢?

继续使用上述方式,会有很大的性能问题,这个时候,有人可能要问,实际中的项目 哪有1w个,10w个元素的。一般的项目可能没有,但是社交类的网站,如微博,其他的如大批量文件上传等能功能,都是需要动态创建dom元素,而且数量巨大,并且创建出来的dom元素,一般都需要绑定事件和相应的特效。一般情况下,用普通的绑定事件方式是不能给动态创建的dom元素绑定到事件的,所以这里就产生了两个问题:

1,当页面元素很多的时候,如果给这些元素绑定上事件?

2,当动态创建dom时,如果给动态创建的dom绑定上事件和相应的特效?

这就是本文需要讨论的模式-委托模式

采用事件委托可以顺利解决上面2个问题

那么,什么是事件委托呢?

给元素的父元素绑定事件,利用冒泡原理,当子元素触发事件的时候,会去触发父元素的事件,然后把相应的业务逻辑放在父元素的事件中去处理。通俗点讲就是,子元素不做事件绑定,把绑定事件的操作委托给父元素,这就叫做事件委托, 委托有一个特性,他能够在事件触发中,识别到具体是由哪个子元素触发的,这个就是事件对象的target属性

     <ul>
<li>跟着ghostwu学习javascript设计模式的应用1</li>
<li>跟着ghostwu学习javascript设计模式的应用2</li>
<li>跟着ghostwu学习javascript设计模式的应用3</li>
<li>跟着ghostwu学习javascript设计模式的应用4</li>
</ul>
<script>
var oUl = document.querySelector("ul");
oUl.addEventListener( "click", ( ev )=>{
var oEvent = ev || event;
target = oEvent.target || oEvent.srcElement;
alert( target.innerHTML );
});
</script>

当我们点击li的时候,就能通过事件对象oEvent.target识别到触发事件的li元素, srcElement是兼容ie的写法。

在没有事件委托之间,我们通过javascript做一个hover的功能,一般这么做.

     <ul>
<li>跟着ghostwu学习设计模式</li>
<li>跟着ghostwu学习设计模式</li>
<li>跟着ghostwu学习设计模式</li>
<li>跟着ghostwu学习设计模式</li>
<li>跟着ghostwu学习设计模式</li>
</ul>
<script>
var aLi = document.getElementsByTagName( "li" );
for( var i = 0, len = aLi.length; i < len; i++ ){
aLi[i].onmouseover = function(){
this.style.backgroundColor = 'red';
}
aLi[i].onmouseout = function(){
this.style.backgroundColor = '';
}
}
</script>

如果li元素很多,就会产生性能问题,而采用委托模式,我们可以这么做

     <ul>
<li>跟着ghostwu学习设计模式1</li>
<li>跟着ghostwu学习设计模式2</li>
<li>跟着ghostwu学习设计模式3</li>
</ul>
<script>
var aLi = document.getElementsByTagName("li");
var oUl = document.getElementsByTagName( "ul" )[0];
oUl.onmouseover = function( ev ){
var oEvent = ev || event;
var target = oEvent.target || oEvent.srcElement;
if ( target.tagName.toLowerCase() == 'li' ) {
target.style.backgroundColor = 'red';
}
}
oUl.onmouseout = function( ev ){
var oEvent = ev || event;
var target = oEvent.target || oEvent.srcElement;
if ( target.tagName.toLowerCase() == 'li' ) {
target.style.backgroundColor = '';
}
}
</script>

通过事件委托,把元素绑定到父元素,大大提高性能

至此,我们解决了第一个问题:当页面元素很多的时候,如果给这些元素绑定上事件

对于新创建的dom元素,普通绑定事件的方式,是不能绑定到这些dom元素的

      <input type="button" value="创建">
<ul>
<li>ghostwu1</li>
<li>ghostwu2</li>
</ul>
<script>
var oBtn = document.getElementsByTagName( "input" )[0];
var oUl = document.getElementsByTagName( "ul" )[0];
var aLi = document.getElementsByTagName( "li" );
oBtn.onclick = function(){
var oLi = document.createElement( "li" );
oLi.innerHTML = 'ghostwu';
oUl.appendChild( oLi );
}
for( var i = 0, len = aLi.length; i < len; i++ ){
aLi[i].onmouseover = function(){
this.style.backgroundColor = 'red';
}
aLi[i].onmouseout = function(){
this.style.backgroundColor = '';
}
} </script>

新创建的li元素,是不能绑定到onmouseover和onmouseout事件的,我们采用委托模式之后,可以这么做

     <input type="button" value="创建">
<ul>
<li>ghostwu1</li>
<li>ghostwu2</li>
</ul>
<script>
var oBtn = document.getElementsByTagName("input")[0];
var oUl = document.getElementsByTagName("ul")[0];
var aLi = document.getElementsByTagName("li");
oBtn.onclick = function () {
var oLi = document.createElement("li");
oLi.innerHTML = 'ghostwu';
oUl.appendChild(oLi);
}
oUl.onmouseover = function( ev ){
var oEvent = ev || event;
var target = oEvent.target || oEvent.srcElement;
if ( target.tagName.toLowerCase() == 'li' ) {
target.style.backgroundColor = 'red';
}
}
oUl.onmouseout = function( ev ){
var oEvent = ev || event;
var target = oEvent.target || oEvent.srcElement;
if ( target.tagName.toLowerCase() == 'li' ) {
target.style.backgroundColor = '';
}
}
</script>

至此,我们解决了第二个问题:当动态创建dom时,如果给动态创建的dom绑定上事件和相应的特效

最后,我们结合委托模式,来实战一个微博发布的功能,微博发布之后,给动态创建的dom元素添加手风琴折叠功能

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<form class="form-horizontal">
<div class="form-group">
<input id="title" type="text" class="form-control" placeholder="请输入标题">
</div>
<div class="form-group">
<textarea name="" id="txt" cols="30" rows="5" class="form-control"></textarea>
</div>
<div class="form-group">
<input type="button" value="发布" class="btn btn-primary" id="btn-publish">
</div>
</form>
</div>
<div class="col-md-offset-3 col-md-6" id="content">
</div>
</div>
</div>
</body>
<script>
var oBtnPublish = document.getElementById("btn-publish");
var aTpl = [
'<div class="panel panel-success">',
'<div class="panel-heading">',
'<h4 class="panel-title">',
'<a href="javascript:;">',
'[title]',
'</a>',
'</h4>',
'</div>',
'<div class="panel-body">',
'[content]',
'</div>',
'</div>'
];
var oContent = document.getElementById( "content" ),
str = aTpl.join( "" ),
title = '', content = '', panelParent = null;
oBtnPublish.onclick = function(){
str = aTpl.join( "" );
title = document.getElementById( "title" ).value;
txt = document.getElementById( "txt" ).value;
str = str.replace( /\[title\]/, title );
str = str.replace( /\[content\]/, txt );
oContent.innerHTML += str;
}
oContent.onclick = function( ev ){
var oEvent = ev || event;
var target = oEvent.target || oEvent.srcElement;
if ( target.tagName.toLowerCase() == 'a' ) {
panelParent = target.parentNode.parentNode.parentNode;
if ( panelParent.children[1].style.display == "block" || panelParent.children[1].style.display == '' ) {
panelParent.children[1].style.display = 'none';
} else {
panelParent.children[1].style.display = 'block';
}
}
}
</script>
</html>

[js高手之路]设计模式系列课程-委托模式实战微博发布功能的更多相关文章

  1. [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表

    所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理, ...

  2. [js高手之路] 设计模式系列课程 - jQuery的extend插件机制

    这里在之前的文章[js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数基础上增加一个extend浅拷贝,可以为对象方便的扩展属性和方法, jquery的插件扩展机制,大致就是这 ...

  3. [js高手之路]设计模式系列课程-发布者,订阅者重构购物车

    发布者订阅者模式,是一种很常见的模式,比如: 一.买卖房子 生活中的买房,卖房,中介就构成了一个发布订阅者模式,买房的人,一般需要的是房源,价格,使用面积等信息,他充当了订阅者的角色 中介拿到卖主的房 ...

  4. [js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数

    一.我们从一个简单的构造函数+原型程序开始 var G = function(){}; G.prototype = { length : 5, size : function(){ return th ...

  5. [js高手之路]设计模式系列课程-单例模式实现模态框

    什么是单例呢? 单,就是一个的意思.例:就是实例化出来的对象,那合在一起就是保证一个构造函数只能new出一个实例,为什么要学习单例模式呢?或者说单例模式有哪些常见的应用场景.它的使用还是很广泛,比如: ...

  6. [js高手之路]设计模式系列课程-设计一个模块化扩展功能(define)和使用(use)库

    模块化的诞生标志着javascript开发进入工业时代,近几年随着es6, require js( sea js ), node js崛起,特别是es6和node js自带模块加载功能,给大型程序开发 ...

  7. [js高手之路] 设计模式系列课程 - DOM迭代器(2)

    如果你对jquery比较熟悉的话,应该用过 eq, first, last, get, prev, next, siblings等过滤器和方法.本文,我们就用迭代设计模式来封装实现,类似的功能 < ...

  8. [js高手之路] 设计模式系列课程 - 迭代器(1)

    迭代器是指通过一种形式依次遍历数组,对象,或者类数组结构中的每个元素. 常见的有jquery中的each方法, ES5自带的forEach方法. 下面我们就来自定义一个类似jquery或者ES5的迭代 ...

  9. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

随机推荐

  1. 关于EasyUI中DataGrid控件的一些使用方法总结

    一,DataGrid         控件的工作流程 1,通过JavaScript将一个空白的div美化成一个空白的Datagrid模板 2,Datagrid模板通过制定的Url发送请求,获取数据   ...

  2. 还在为CSS布局发愁?你该看看这7条原则

    一.网页结构分析七条原则 这以下7个原则是经过多年网站实战经验之后的总结,只要掌握这7个原则,可以解决大部分在编写网站布局中的问题. 1.先结构后样式. 2.能用CSS表现出来的效果,就尽量少用图像. ...

  3. Linux文件系统,ntfs分区显示只读文件系统,提示超级快损坏

    背景:某天当我打开自己的设备,突然发现ntfs分区无法写入任何文件,提示为只读文件系统,具体现象如下: 修复过程:排除权限问题,使用fsck进行修复无果后,使用e2fsck进行修复 显示超级快损坏,这 ...

  4. jsp页面中某个src,如某个iframe的src,应该填写什么?可以是html、jsp、servlet、action吗?是如何加载的?

    jsp页面中某个src,如某个iframe的src,应该填写什么?可以是html.jsp.servlet.action吗?是如何加载的? 如有个test工程,其某个jsp中有个iframe,代码如下: ...

  5. JavaScript中正则表达式判断匹配规则以及常用的方法

    JavaScript中正则表达式判断匹配规则以及常用的方法: 字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在. 正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想 ...

  6. ps命令用法

    转自:http://www.cnblogs.com/peida/archive/2012/12/19/2824418.html Linux中的ps命令是Process Status的缩写.ps命令用来 ...

  7. websocket 70K连接测试

    websocket 70K连接测试 最近使用socket.io做了一个实时应用,实时性.稳定性还是很让人满意的.如果拿socket.io来做小型应用,综合效率应该是最高的.但是网上少有socket.i ...

  8. Java 冒泡排序的实现

    实现原理: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有的元素重复以上的步骤,除 ...

  9. 【FlashPlayer】-Debug版本-开发人员推荐

    Adobe的Flash-Player的版本分为“普通版本”和“Debug版本”,后者可以协助开发者测试和调试程序. 那么,先给出Debug版本的下载地址:http://www.adobe.com/su ...

  10. 初识webview

    一.什么是webview   原生APP开发中有一个webview的组件(Android中是webview,iOS7以下有UIWebview,7以上有WKWebview),这个组件可以加载Html文件 ...