在使用 Datatables 表格插件开发过程中,给每一列的表头增加了自定义的列筛选功能,具体是给表头增加了一个可点击的图标,点击图标触发筛选,但是发现点击图标的时候同时会触发 Datatables 自带的排序功能。

点击图标触发筛选.PNG

html 结构如下:

  <th class="_name indicator title sorting" tabindex="0" aria-controls="table-abs" rowspan="1" colspan="1" style="width: 250px;" aria-label="项目名称: activate to sort column ascending">
      项目名称
      <!-- 列筛选图标 -->
      <i class="addSelect" data-column="1"><span class="icon-caret-down"></span></i>
  </th>

js 代码如下:

  // 点击列筛选图标
  $('.table-section').off('.customSearch').on('click.customSearch', 'th.title .addSelect', function (evt) {
    evt.stopPropagation();
    // dosomething ...
  });

这种事件委托的事件绑定方式,在这里出现了事件冒泡,虽然调用了 evt.stopPropagation(); ,但仍然会触发绑定在 th.title 上的排序事件。

JS事件代理不是基于事件冒泡么,如果委托元素和目标元素之间还有元素绑定了相同事件,如何阻止事件冒泡? -- 知乎

实际上,事件委托的事件处理函数是当被委托的元素上的事件触发时判断e.target后执行,而不是目标元素上的事件被触发后就立即执行,在没有阻止冒泡的情况下,事件还是一层层传播的,只是处理函数在事件到达那一层被触发的问题。根据事件代理的规则,点击li元素后,click事件是从li至inner至outer一层层冒泡上去的,沿途触发各个元素上的事件处理函数,如果我们将事件委托在outer上,即使调用了stopPropagation,也只是阻止了事件从outer向上冒泡,而之前的冒泡过程必然会触发inner上的click事件,执行处理函数,但是如果将事件委托在inner上,并且阻止冒泡,阻止的是从inner开始的冒泡,这样就可以阻止inner及其祖先元素上的click事件被触发。

作者:echizen
链接:https://www.zhihu.com/questio...


澄海风
300 声望15 粉丝

前端开发 | 星汉西流夜未央