问题说明

利用 [vue-seamless-scroll](https://github.com/chenxuan0000/vue-seamless-scroll) 实现了一个图片的轮播,流转效果。

当只有一个时,会再创建一个一模一样的Html,给 li 添加了点击事件,但是没有作用,没有反应。

代码如下:

<div class="list" v-if="list.length != 0" >
  <vue-seamless-scroll
    :data="list"
    :class-option="{
          step: 0.4, // 数值越大速度滚动越快
          limitMoveNum: 1, // 开始无缝滚动的数据量 this.dataList.length
          hoverStop: true, // 是否开启鼠标悬停stop
          direction: 2, // 0向下 1向上 2向左 3向右
          openWatch: true, // 开启数据实时监控刷新dom
          singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
          singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
          waitTime: 2000,
        }"
    >
    <ul>
      <li
        v-for="(item, index) in list"
        :key="index"
        class="listItem"
        @click="handleDetail(item)"
      >
        <div class="img">
        	<img :src="handleSrc(item)" :alt="item.title" />
        </div>
        <div class="bot">
        	<div class="title">{{ item.title }}</div>
        </div>
      </li>
    </ul>
  </vue-seamless-scroll>
</div>
<el-empty v-else></el-empty>

问题解决

1.分析 vue-seamless-scroll

vue-seamless-scroll 有部分点击没反应问题_事件委托

vue-seamless-scroll 有部分点击没反应问题_前端_02

可以看到,有一部分是直接使用的  slot(我们自己定义的元素)里面渲染之后的html,并没有绑定事件。

2.使用事件委托实现子元素的点击事件处理

1. 说明:

事件委托理解:https://cloud.tencent.com/developer/article/2434471

2. 知识简要回顾:

1)事件流:一个完整的事件流包括三个阶段:事件捕获、目标阶段和事件冒泡阶段。

2)事件冒泡:事件从目标元素接收,逐层往父组件传播直至 document。(有些事件不支持冒泡,如focus等等)

3)事件捕获:与冒泡相反,从document 往里直至目标元素接收到。

4)事件委托:就是利用事件流中的冒泡效应,将子元素的处理程序统一绑定到父元素上,针对动态渲染的子元素较为友好。

将事件统一放到外层的 div 上,点击之后,利用  composedPath 来获取到 子元素绑定的 data-index 数据,来触发点击事件。

<div class="list" v-if="list.length != 0" @click="delegateDetail($event)">
  ...<li
        v-for="(item, index) in list"
        :key="index"
        class="listItem"
        :data-index="index"
      >
  ...
  
  // 代理查看明细
  delegateDetail(e) {
      const path = e.path || (e.composedPath && e.composedPath())
      let target = path.filter(r => /listItem/.test(r.className))
      if (target.length) target = target[0]
      else return
      const index = JSON.parse(target.getAttribute('data-index'))
  		this.handleDetail(this.list[index])
    }