问题说明
利用 [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
可以看到,有一部分是直接使用的 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])
}