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

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

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

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

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

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

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

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

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

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

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

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

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

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

 1     <ul>
 2         <li>跟着ghostwu学习设计模式</li>
 3         <li>跟着ghostwu学习设计模式</li>
 4         <li>跟着ghostwu学习设计模式</li>
 5         <li>跟着ghostwu学习设计模式</li>
 6         <li>跟着ghostwu学习设计模式</li>
 7     </ul>
 8     <script>
 9         var aLi = document.getElementsByTagName( "li" );
10         for( var i = 0, len = aLi.length; i < len; i++ ){
11             aLi[i].onmouseover = function(){
12                 this.style.backgroundColor = 'red';
13             }
14             aLi[i].onmouseout = function(){
15                 this.style.backgroundColor = '';
16             }
17         }
18     </script>

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

 1     <ul>
 2         <li>跟着ghostwu学习设计模式1</li>
 3         <li>跟着ghostwu学习设计模式2</li>
 4         <li>跟着ghostwu学习设计模式3</li>
 5     </ul>
 6     <script>
 7         var aLi = document.getElementsByTagName("li");
 8         var oUl = document.getElementsByTagName( "ul" )[0];
 9         oUl.onmouseover = function( ev ){
10             var oEvent = ev || event;
11             var target = oEvent.target || oEvent.srcElement;
12             if ( target.tagName.toLowerCase() == 'li' ) {
13                 target.style.backgroundColor = 'red';
14             }
15         }
16         oUl.onmouseout = function( ev ){
17             var oEvent = ev || event;
18             var target = oEvent.target || oEvent.srcElement;
19             if ( target.tagName.toLowerCase() == 'li' ) {
20                 target.style.backgroundColor = '';
21             }
22         }
23     </script>

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

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

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

 1      <input type="button" value="创建">
 2    <ul>
 3        <li>ghostwu1</li>
 4        <li>ghostwu2</li>
 5    </ul>
 6     <script>
 7         var oBtn = document.getElementsByTagName( "input" )[0];
 8         var oUl = document.getElementsByTagName( "ul" )[0];
 9         var aLi = document.getElementsByTagName( "li" );
10         oBtn.onclick = function(){
11             var oLi = document.createElement( "li" );
12             oLi.innerHTML = 'ghostwu';
13             oUl.appendChild( oLi );
14         }
15         for( var i = 0, len = aLi.length; i < len; i++ ){
16             aLi[i].onmouseover = function(){
17                 this.style.backgroundColor = 'red';
18             }
19             aLi[i].onmouseout = function(){
20                 this.style.backgroundColor = '';
21             }
22         }
23
24     </script>

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

 1     <input type="button" value="创建">
 2     <ul>
 3         <li>ghostwu1</li>
 4         <li>ghostwu2</li>
 5     </ul>
 6     <script>
 7         var oBtn = document.getElementsByTagName("input")[0];
 8         var oUl = document.getElementsByTagName("ul")[0];
 9         var aLi = document.getElementsByTagName("li");
10         oBtn.onclick = function () {
11             var oLi = document.createElement("li");
12             oLi.innerHTML = 'ghostwu';
13             oUl.appendChild(oLi);
14         }
15         oUl.onmouseover = function( ev ){
16             var oEvent = ev || event;
17             var target = oEvent.target || oEvent.srcElement;
18             if ( target.tagName.toLowerCase() == 'li' ) {
19                 target.style.backgroundColor = 'red';
20             }
21         }
22         oUl.onmouseout = function( ev ){
23             var oEvent = ev || event;
24             var target = oEvent.target || oEvent.srcElement;
25             if ( target.tagName.toLowerCase() == 'li' ) {
26                 target.style.backgroundColor = '';
27             }
28         }
29     </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高手之路]设计模式系列课程-发布者,订阅者重构购物车

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

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

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

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

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

  4. [js高手之路] vue系列教程 - vue的事件绑定与方法(2)

    一.在vue中,绑定事件,用v-on:事件类型, 如绑定一个点击事件, 我们可以这样子做 1 window.onload = function () { 2 var c = new Vue({ 3 e ...

  5. [js高手之路]html5 canvas动画教程 - 下雪效果

    利用canvas,实现一个下雪的效果,我们先预览下效果: 我们先分析下这个效果: 1,随机产生雪花 2,雪花的产生不是同时产生,而是有先后顺序的 3,雪花怎么表示 4,怎么源源不断的下雪 5,雪花有大 ...

  6. [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  7. [js高手之路] html5 canvas系列教程 - 线条样式(lineWidth,lineCap,lineJoin,setLineDash)

    上文,写完弧度与贝塞尔曲线[js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具),本文主要是关于线条的样式设置 lineWidth: 设置线条的宽 ...

  8. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API

    我们接着上文[js高手之路] html5 canvas系列教程 - 认识canvas以及基本使用方法继续. 一.直线的绘制 cxt.moveTo( x1, y1 ): 将画笔移动到x1, y1这个点 ...

  9. HTML弧度文本,[js高手之路] html5 canvas系列教程 - 文本样式(strokeText,fillText,measureText,textAlign,textBaseline)...

    canvas提供两种输出文本的方式: strokeText:描边文本 fillText:填充文本 fillStyle配合fillText使用,strokeStyle配合strokeText使用 str ...

  10. 前端画圆弧html弧线的像素,[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形)...

    arc:画弧度 cxt.arc( x, y, 半径, 开始角度,结束角度,是否逆时针 ); x, y: 为弧度的中心横坐标和纵坐标,如果这是画一个圆.那么x,y就是圆的圆心. 开始角度与结束角度都是以 ...

最新文章

  1. C++ Primer Plus(十)——对象和类
  2. 线程中CreateEvent和SetEvent及WaitForSingleObject的用法
  3. 机器学习-特征中的相关性及相关系数、卡方检验、互信息
  4. EasyUI中Accordion折叠面板的简单使用
  5. 数据可视化模板_10分钟,做一份数据可视化分析报表
  6. linux下调试core的命令
  7. 2024.常见一些设计类模板
  8. pythoncanny边缘检测自适应阈值_一种自适应阈值的Canny边缘检测算法
  9. 腾讯云,搭建Git服务器
  10. shark恒破解笔记3-EAX决定胜负
  11. VSCODE + 搜狗输入法,文字突然变成了繁体字,为什么?
  12. 字符串处理,仿古书竖排版
  13. 芯准TTE“宏时隙“调度机制 ——基本原理
  14. 2020个人成长计划
  15. 达梦数据库角色详解——VTI、SOI
  16. 由内建质量到持续集成
  17. keil的c语言基础,KeilC单片机C语言应用研究入门基础篇要点S.doc
  18. Vue + Element 实现导入导出Excel
  19. 爱奇艺UI赏析—首页推荐
  20. 串口服务器 信号,信号隔离转换模块(RS232\RS485串口服务器安全栅) - 万维电子----I类防爆电气|II类防爆电气|本安人机界面|工业平板电脑...

热门文章

  1. paip.陕北方言 广东方言的不同单字 1千高频字
  2. paip.c3p0 数据库连接池 NullPointerException 的解决...
  3. paip.;论全文检索实现方式lucene Sphinx solr以及比较
  4. paip.提升用户体验---c++ qt自定义窗体(2)---边框线的绘制
  5. paip.c++读写ini文件.
  6. 数据治理的坑你遇到过几个?
  7. (转)被动投资--傻钱的泡沫
  8. CSDN创始人董事长蒋涛对话阿里云张献涛:距离云计算终极目标还有多远?
  9. 【手势识别】基于matlab PCA+LDA手语检测识别【含Matlab源码 1551期】
  10. 【阙值分割】基于matlab遗传算法自适应多阈值图像分割【含Matlab源码 1460期】