Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【20170204】JS事件委托 #69

Closed
zhongxia245 opened this issue Feb 4, 2017 · 1 comment
Closed

【20170204】JS事件委托 #69

zhongxia245 opened this issue Feb 4, 2017 · 1 comment

Comments

@zhongxia245
Copy link
Owner

zhongxia245 commented Feb 4, 2017

时间:2016-12-03 15:20:07

问题

什么是事件委托?

一、事件冒泡

DOM2级 事件分为三个阶段(IE8以及之前不支持DOM事件流)

  • 事件捕获
  • 目标对象
  • 冒泡

W3C模型:
页面上的点击事件流程是这样的, 从不准确节点 document,HTML开始一层一层的往下找,直到找到绑定目标事件的对象, 找到之后,事件会在一层一层的冒泡,冒泡到最顶层。

//第三个参数默认是 false, 标识事件触发在冒泡阶段
先执行目标事件处理函数,在处理父容器的事件。

如果为true的话, 先执行父容器的事件,在执行目标事件

addEventListener(eventname,fn,useCaptrue)

二、事件委托

把多个有相同事件处理函数的节点,把事件绑定到他们的父节点上。减轻对内存的损耗

  • 根据事件冒泡的原理,衍生出委托事件

js事件委托,其实是使用了冒泡的原理,从点击的元素开始,递归方式的向父元素传播事件,这样做的好处是对于大量要处理的元素,不必为每个元素都绑定事件,只需要在他们的父元素上绑定一次即可,提高性能。 还有一个好处就是可以处理动态插入dom中的元素,直接绑定的方式是不行的。
就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素事件委托很好地利用了"事件冒泡"。当点击子元素,根据"事件冒泡",该子元素的父级元素捕获了该次点击事件,并触发自己的方法。

1. 优点

  • 提升性能【每个节点绑定事件,到把事件绑定到父容器上】
  • 新增的元素还会有之前的处理事件

2. 缺点

  • 不是所有的事件都能冒泡。 【focus, blur, load, unload】
  • 在管理鼠标事件的时候,需要注意,因为鼠标事件太频繁了,如果鼠标事件处理有问题,就容易造成性能瓶颈

三、demo

<ul id="parent-list">
    <li id="post-1">Post 1</li>
    <li id="post-2">Post 2</li>
    <li id="post-3">Post 3</li>
    <li id="post-4">Post 4</li>
    <li id="post-5">Post 5</li>
    <li id="post-6">Post 6</li>
</ul>

给所有 li 绑定事件

  • 写一个循环,给每一个 li 绑定上 click 事件
  • 把事件绑定在ul 上, 通过 e.target 可以获取点击节点的信息

四、Jquery的事件委托

$(document).on(‘click‘,‘li‘,function(){
    alert(‘这是一个li!!!‘);
});

用JS封装一个

/**
    
*/
function delegate(parent,selector,eventName,callback){
    
}
/**
   * 事件委托
   * @param  {[type]}   dom       [绑定事件的DOM节点]
   * @param  {[type]}   selector  [需要绑定的子节点]
   * @param  {[type]}   eventName [事件名称]
   * @param  {Function} callback  [事件处理函数]
   * @return {[type]}             []
   */
  function delegate(dom, selector, eventName, callback) {
  	if(dom){
  		dom.addEventListener(eventName,function(e){
  			e = e || window.event
  			if(e.target.tagName.toLowerCase() === selector){
  				callback && callback(e)
  			}
			})
  	}
  }

完整的事件委托方法

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>事件委托</title>
</head>

<body>
  <ul id="id-ul">
    <li>zhongxia1</li>
    <li>zhongxia2</li>
    <li>zhongxia3</li>
    <li>zhongxia4</li>
  </ul>
  <button id="id-btn">添加一个li</button>
  <script type="text/javascript">
  var ul = document.querySelector('#id-ul')
  delegate(ul, 'li', 'click', function(e) {
    console.log(e.target)
  })

  addEvent(document.querySelector('#id-btn'), 'click', function() {
  	ul.innerHTML += '<li>动态添加的Item</li>'
  })

  /**
   * 事件委托
   * @param  {[type]}   dom       [绑定事件的DOM节点]
   * @param  {[type]}   selector  [需要绑定的子节点]
   * @param  {[type]}   eventName [事件名称]
   * @param  {Function} callback  [事件处理函数]
   * @return {[type]}             []
   */
  function delegate(dom, selector, eventName, callback) {
    if (dom) {
      addEvent(dom, eventName, function(e) {
        e = e || window.event
        if (e.target.tagName.toLowerCase() === selector) {
          callback && callback(e)
        }
      },false)
    }
  }

  function addEvent(elm, evType, fn, useCapture) {
    if (elm.addEventListener) {
      elm.addEventListener(evType, fn, !!useCapture); //DOM2.0
      return true;
    } else if (elm.attachEvent) {
      var r = elm.attachEvent('on' + evType, fn); //IE5+
      return r;
    } else {
      elm['on' + evType] = fn; //DOM 0
    }
  }
  </script>
</body>

</html>
@zhongxia245 zhongxia245 changed the title #20170204 事件委托 【20170204】JS事件委托 Feb 5, 2017
@cji03
Copy link

cji03 commented Oct 24, 2017

delegate方法中,if (e.target.tagName.toLowerCase() === 'li')应该等于selector吧,你这写死了。然后e.target也应该hack一下。

addEventuseCapture应该是Ture或者False吧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants