全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解js的事件代理(委托)

JavaScript事件代理(委托)一般用于以下情况:

  1. 事件注册在祖先级元素上,代理其子级元素。可以减少事件注册数量,节约内存开销,提高性能。

  2. 对js动态添加的子元素可自动绑定事件。

之前一直用各种js库的事件代理,如 jQuery,非常方便实用。今天尝试用原生 js 实现该功能。

var addEvent = (function () {
 if (document.addEventListener) {
 return function (element, type, handler) {
 element.addEventListener(type, handler, false);
 };
 } else if (document.attachEvent) {
 return function (element, type, handler) {
 element.attachEvent('on' + type, function () {
 handler.apply(element, arguments);
 });
 };
 } else {
 return function (element, type, handler) {
 element['on' + type] = function () {
 return handler.apply(element, arguments);
 };
 };
 }
})(),
getClassElements = function (parentElement, classname) {
 var all, element, classArr = [], classElements = [];
 if (parentElement.getElementsByClassName) {
 return parentElement.getElementsByClassName(classname);
 } else {
 all = parentElement.getElementsByTagName('*');
 for (var i = 0, len = all.length; i < len; i++) {
 element = all[i];
 classArr = element && element.className && element.className.split(' ');
 if (classArr) {
 for (var j = 0; j < classArr.length; j++) {
  if (classArr[j] === classname) {
  classElements.push(element);
  }
 }
 }
 }
 return classElements;
 }
},
delegate = function () { // 参数:element, type, [selector,] handler
 var args = arguments,
 element = args[0],
 type = args[1],
 handler;
 if (args.length === 3) {
 handler = args[2];
 return addEvent(element, type, handler);
 }
 if (args.length === 4) {
 selector = args[2];
 handler = args[3];
 return addEvent(element, type, function (event) {
 var event = event || window.event,
 target = event.target || event.srcElement,
 quickExpr = /^(?:[a-zA-Z]*#([\w-]+)|(\w+)|[a-zA-Z]*\.([\w-]+))$/,
 match,
 idElement,
 elements,
 tagName,
 count = 0,
 len;
 if (typeof selector === 'string') {
 match = quickExpr.exec(selector);
 if (match) {
  // #ID selector
  if (match[1]) {
  idElement = document.getElementById(match[1]);
  tagName = match[0].slice(0, match[0].indexOf('#'));
  // tag selector
  } else if (match[2]) {
  elements = element.getElementsByTagName(selector);
  // .class selector
  } else if (match[3]) {
  elements = getClassElements(element, match[3]);
  tagName = match[0].slice(0, match[0].indexOf('.'));
  }
 }
 if (idElement) {
  if ( tagName ? tagName === idElement.nodeName.toLowerCase() && target === idElement : target === idElement ) {
  return handler.apply(idElement, arguments);
  }
 } else if (elements) {
  for (len = elements.length; count < len; count++) {
  if ( tagName ? tagName === elements[count].nodeName.toLowerCase() && target === elements[count] : target === elements[count] ) {
  return handler.apply(elements[count], arguments);
  }
  }
 }
 }
 });
 }
};

主要是用 apply 改变 this 的指向

handler.apply(idElement, arguments);
handler.apply(elements[count], arguments);

测试一下:

<style>
#outer {padding: 50px; background-color: lightpink;}
#inner {padding: 30px; background-color: aliceblue;}
#paragraph1, #paragraph3 {background-color: cadetblue}
</style>
<div id="outer">outer
 <div id="inner">inner
 <p id="paragraph1" class="parag1">paragraph1</p>
 <p id="paragraph2" class="parag">paragraph2</p>
 <span>span</span>
 <p id="paragraph3" class="parag">paragraph3</p>
 </div>
</div>
var outer = document.getElementById('outer');
delegate(outer, 'click', function () {
 console.log(this.id); // outer
});
delegate(outer, 'click', 'p', function () {
 console.log(this.id); //点击 paragraph1 元素,输出其id为 "paragraph1"
});

模仿 jQuery 的风格,优化代码:

(function () {
 var $ = function (element) {
 return new _$(element);
 };
 var _$ = function (element) {
 this.element = element && element.nodeType === 1 ? element : document;
 };
 _$.prototype = {
 constructor: _$,
 addEvent: function (type, handler, useCapture) {
 var element = this.element;
 if (document.addEventListener) {
 element.addEventListener(type, handler, (useCapture ? useCapture : false));
 } else if (document.attachEvent) {
 element.attachEvent('on' + type, function () {
  handler.apply(element, arguments);
 });
 } else {
 element['on' + type] = function () {
  return handler.apply(element, arguments);
 };
 }
 return this;
 },
 getClassElements: function (classname) {
 var element = this.element, all, ele, classArr = [], classElements = [];
 if (element.getElementsByClassName) {
 return element.getElementsByClassName(classname);
 } else {
 all = element.getElementsByTagName('*');
 for (var i = 0, len = all.length; i < len; i++) {
  ele = all[i];
  classArr = ele && ele.className && ele.className.split(' ');
  if (classArr) {
  for (var j = 0; j < classArr.length; j++) {
  if (classArr[j] === classname) {
  classElements.push(ele);
  }
  }
  }
 }
 return classElements;
 }
 },
 delegate: function () { //参数:type, [selector,] handler
 var self = this,
 element = this.element,
 type = arguments[0],
 handler;
 if (arguments.length === 2) {
 handler = arguments[1];
 return self.addEvent(type, handler);
 } else if (arguments.length === 3) {
 selector = arguments[1];
 handler = arguments[2];
 return self.addEvent(type, function (event) {
  var event = event || window.event,
  target = event.target || event.srcElement,
  quickExpr = /^(?:[a-zA-Z]*#([\w-]+)|(\w+)|[a-zA-Z]*\.([\w-]+))$/,
  match,
  idElement,
  elements,
  tagName,
  count = 0,
  len;
  if (typeof selector === 'string') {
  match = quickExpr.exec(selector);
  if (match) {
  // #ID selector
  if (match[1]) {
  idElement = document.getElementById(match[1]);
  tagName = match[0].slice(0, match[0].indexOf('#'));
  // tag selector
  } else if (match[2]) {
  elements = element.getElementsByTagName(selector);
  // .class selector
  } else if (match[3]) {
  elements = self.getClassElements(match[3]);
  tagName = match[0].slice(0, match[0].indexOf('.'));
  }
  }
  if (idElement) {
  if ( tagName ? tagName === idElement.nodeName.toLowerCase() && target === idElement ? target === idElement ) {
  return handler.apply(idElement, arguments);
  }
  } else if (elements) {
  for (len = elements.length; count < len; count++) {
  if ( tagName ? tagName === elements[count].nodeName.toLowerCase() && target === elements[count] : target === elements[count] ) {
   return handler.apply(elements[count], arguments);
  }
  }
  }
  }
 });
 }
 }
 };
 window.$ = $;
 return $;
}());

使用如下:

var outer = document.getElementById('outer');
$(outer).delegate('click', '.parag', function (event) {
 console.log(this.id);
});

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# js  # 事件代理  # js事件委托和事件代理案例分享  # js中的事件委托或是事件代理使用详解  # JavaScript事件代理和委托详解  # 深入分析Javascript事件代理  # 浅析javascript中的事件代理  # JavaScript通过事件代理高亮显示表格行的方法  # JavaScript的事件代理和委托实例分析  # javascript中的事件代理初探  # JavaScript 事件代理需要注意的地方  # 绑定  # 可以减少  # 其子  # 主要是  # 测试一下  # getElementsByTagName  # getElementsByClassName  # length  # len  # classElements  # classname  # parentElement  # getClassElements  # classArr  # lt  # event  # args  # window  # srcElement  # target 


相关文章: 建站主机空间推荐 高性价比配置与快速部署方案解析  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  高防服务器租用首荐平台,企业级优惠套餐快速部署  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  长春网站建设制作公司,长春的网络公司怎么样主要是能做网站的?  建站主机选购指南与交易推荐:核心配置解析  简历在线制作网站免费版,如何创建个人简历?  制作网页的网站有哪些,电脑上怎么做网页?  制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?  怀化网站制作公司,怀化新生儿上户网上办理流程?  为什么Go需要go mod文件_Go go mod文件作用说明  浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?  制作网站的过程怎么写,用凡科建站如何制作自己的网站?  制作宣传网站的软件,小红书可以宣传网站吗?  湖北网站制作公司有哪些,湖北清能集团官网?  上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?  非常酷的网站设计制作软件,酷培ai教育官方网站?  如何在IIS中新建站点并解决端口绑定冲突?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  公众号网站制作网页,微信公众号怎么制作?  北京营销型网站制作公司,可以用python做一个营销推广网站吗?  青岛网站建设如何选择本地服务器?  威客平台建站流程解析:高效搭建教程与设计优化方案  如何高效配置IIS服务器搭建网站?  香港服务器网站卡顿?如何解决网络延迟与负载问题?  建站之星logo尺寸如何设置最合适?  建站之星五站合一营销型网站搭建攻略,流量入口全覆盖优化指南  如何在阿里云完成域名注册与建站?  微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?  建站之星如何配置系统实现高效建站?  如何选择最佳自助建站系统?快速指南解析优劣  在线制作视频网站免费,都有哪些好的动漫网站?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  如何用VPS主机快速搭建个人网站?  如何用花生壳三步快速搭建专属网站?  网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?  网站网页制作专业公司,怎样制作自己的网页?  建站之星备案流程有哪些注意事项?  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何解决ASP生成WAP建站中文乱码问题?  nginx修改上传文件大小限制的方法  制作销售网站教学视频,销售网站有哪些?  css网站制作参考文献有哪些,易聊怎么注册?  如何制作算命网站,怎么注册算命网站?  如何快速生成高效建站系统源代码?  北京制作网站的公司,北京铁路集团官方网站?  php8.4新语法match怎么用_php8.4match表达式替代switch【方法】  已有域名和空间,如何快速搭建网站?  建站之星免费模板:自助建站系统与智能响应式一键生成  网站制作大概要多少钱一个,做一个平台网站大概多少钱? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。