[] 嵌套标签过多时,实现事件委托

2018-09-10  本文已影响36人  Bboy_2016

1,问题出现场景:
有得时候我们要所点击元素的父级,例如这种情况,
ul
li
span
...
我们点击span(多数会点击到),其实是想对 li 进行操作,但是由于是事件委托,不得不把事件放到 ul 上(可能是要少写代码)。所以便有如下代码。
上面一层是我用来测试的html
下面是 原生 js 实现,其实还可以参考下 jquery 的实现方式。类似于这种,

$('ul').on('click', 'li', function (e) {}) // 这样绑定的话 e.currentTarget 就是 li

但是我没有jq的环境,所以,No.

代码源于网络,侵删

大致 html 如下:
  const list = [1,2,3,4,5]
  render: function (createElement) {
    return createElement(
      'ul', {
        attrs: {
          id: 'list',
        },
        style: {
          'fontSize': '24px'
        },
        'on': {
          click: this.handler
        }
      }, [
        list.map((item) => {
          return createElement('li', {
          }, [createElement('span', item)])
        })
      ]
    )
  }
    function eventDelegate (parentSelector, targetSelector, events, foo) {
      // 触发执行的函数
      function triFunction (e) {
        // 兼容性处理
        var event = e || window.event;

        // 获取到目标阶段指向的元素
        var target = event.target || event.srcElement;

        // 获取到代理事件的函数
        var currentTarget = event.currentTarget;

        // 处理 matches 的兼容性
        if (!Element.prototype.matches) {
          Element.prototype.matches =
            Element.prototype.matchesSelector ||
            Element.prototype.mozMatchesSelector ||
            Element.prototype.msMatchesSelector ||
            Element.prototype.oMatchesSelector ||
            Element.prototype.webkitMatchesSelector ||
            function (s) {
              var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
              while (--i >= 0 && matches.item(i) !== this) {}
              return i > -1;            
            };
        }

        // 遍历外层并且匹配
        while (target !== currentTarget) {
          // 判断是否匹配到我们所需要的元素上
          if (target.matches(targetSelector)) {
            var sTarget = target;
            // 执行绑定的函数,注意 this
            foo.call(sTarget, Array.prototype.slice.call(arguments))
          }

          target = target.parentNode;
        }
      }

      // 如果有多个事件的话需要全部一一绑定事件
      events.split('.').forEach(function (evt) {
        // 多个父层元素的话也需要一一绑定
        Array.prototype.slice.call(document.querySelectorAll(parentSelector)).forEach(function ($p) {
          $p.addEventListener(evt, triFunction)
        })
      })
    }
    eventDelegate('#list', 'li', 'click', function () { console.log(this) })

结果如下:


event delegation.png
上一篇 下一篇

猜你喜欢

热点阅读