欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

使用JQ和原生JS实现事件代理:on方法与addEventListener的比较

最编程 2024-08-07 14:47:20
...

事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)。
原理:事件委托是利用事件的冒泡原理来实现的 。事件监听器会分析从子元素冒泡上来的事件,找到是哪个子元素的事件。
————————————————
比较早的jq写的,没有ES6模板字符串,就js拼接字符串。
大概有个类似这样的需求

image.png

  • 点击左边+号右边添加,再点击,取消灰色并移除右边的菜单项;
  • 左边添加后,也可以通过右边的x来删除,同时移除左边菜单块灰色。
    左边就是拿到数据,拼接DOM元素,放进去,这是就用到了事件委托通过子节点元素绑定事件来传递给父元素DOM节点,父元素代子元素执行事件,来统一管理其全部后代子元素
    tips:对应标签绑定事件这样很不推荐,原因如下(参考忘了)
  1. 绑定事件太多,浏览器占用内存变大,严重影响性能;
  2. Ajax出现,局部刷新盛行,每次加载完,都要重新绑定事件;
  3. 部分浏览器移除元素时,绑定的事件没有被及时移除,导致内存泄漏,严重影响性能;
  4. Ajax中重复绑定,导致代码耦合性过大,影响后期维护
// 左侧选择添加菜单的方法
function clickPlus(obj) {
 $(obj).parent().toggleClass('gray')
 var name = $(obj).parent().attr('data-name')
 if ($(obj).parent().hasClass('gray')) {
   var html = ''
   html += '<div class="cont-item" data-name=' + name + '>'
   html += '<span class="name">' + name + '</span>'
   html += '<span class="delete">x</span>'
   html += '</div>'
   $('.content').append(html)
 } else {
   deleteItem(name)
 }
}
<div class="submit" onclick="submit(this)"></div>

.html文件中可以直接传this指向的是当前标签,所以,
刚开始想在span上绑定onclick把name和this都传过去,这样当前知道选择的元素就可以直接remove()掉了,如下

html += '<span class="plus" onclick="clickPlus(this,\''+item.name+'\')">+</span>'

但参数多的话容易出问题,还影响性能等等,就转为事件委托,避免此种情况

// 右边直接点击删除按钮
$('.content').on('click', $('.cont-item'), function (ev) {
  var delName = $(ev.target).parent().attr('data-name')
  var menuArr = $('.right-item .bar')
  $.each(menuArr, function (index, item) {
    if (delName == $(item).attr('data-name')) $(item).toggleClass('gray')
  })
  $(ev.target).parent().remove()
})

remove时如果出错,可加一层判断

if($(ev.target).prop('nodeName')=="SPAN")  ...remove()

假如.on那一行改成

//会自动找.cont-item,不需要加$符号指定,这样也就不用判断nodeName这样更常见
$('.content').on('click', '.cont-item', function (ev) { 

比起bind、delegate使用on更推荐,
$('父元素').on('click', $('子元素'),function(ev){...})

原生js例子:

<ul id = "lists">
    <li>列表1</li>
    <li>列表2</li>
    <li>列表3</li>
    <li>列表4</li>
    <li>列表5</li>
    <li>列表6</li>
 </ul>
var lists = document.getElementById("lists");
lists.addEventListener("click",function(event){
  var target = event.target;
   //防止父元素ul也触发事件
  if(target.nodeName == "LI"){
    target.style.backgroundColor = "red";
  }
})

推荐阅读