赞
踩
使用vue-seamless-scroll实现数据无缝连续滚动
无限滚动原理:无限滚动的原理就是把之前的遍历的内容复制一份,滚动这两部分内容,达到无缝滚动效果。
基本原理是把要滚动的部分复制一份,滚动这两部分相同的内容,进而实现无缝连续滚动
当ul1中的数据未滚动完时,ul2 部分的click事件不起作用,无法实现点击这行功能
(此时可见区域内一部分数据为ul1,一部分数据为ul2)
直接现象:
在使用vue-seamless-scroll 自动滚屏绑定事件时,个别点击事件无效
原因:
该插件为了实现无缝衔接而复制了dom渲染,不会带上事件。
解决办法:
利用js事件委托机制。
1.1、结构
原来是在li里面绑定事件出现上述问题,现在给最外层的父级div加委托事件,让父级事件执行。
通过 e.target.dataset.code 获取所需值
备注:
vue中自定义属性格式为 data-xxx
获取为:e.target.dataset.xxx
id 和 name 一般为部分标签自带属性,前面不需要加data
事件委托依靠的就是事件冒泡和事件捕获的机制
事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。
事件捕获会从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。
所谓的事件委托就是通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数,从而提升速度。
1、事件委托
2、JavaScript 运行机制详解:再谈Event Loop
在项目中碰到一个走马灯需求,选择使用vue-seamless-scroll插件进行解决
<template>
<section class="footer-info">
<vueSeamless :data="infoList" :class-option="options">
<p v-for="info in infoList" :key="info.id">
<!-- handleDetailClick 点击事件绑在目标元素上 -->
<span @click="handleDetailClick(info.id)">{{info.detail}}</span>
</p>
</vueSeamless>
</section>
</template>
现象:实际页面渲染后会出现点击某些span没有执行事件的情况。
原因:是因为vue-seamless-scroll是用重复渲染一遍内部元素来实现滚动的,而JS的onclick只检测页面渲染时的DOM元素。
思路:在section上绑定事件handleSectionClick,捕获点击的DOM节点,若为span则执行事件。事件中需求的数据可以直接用data绑在相应的span上。
<template> <!-- 1.0、handleSectionClick 点击事件绑在目标元素的父元素上 --> <!-- @click.stop 阻止事件冒泡;也可直接写@click --> <section class="footer-info" @click.stop="handleSectionClick($event)"> <vueSeamless :data="infoList" :class-option="options"> <p v-for="info in infoList" :key="info.id"> <span :data-id="info.id">{{info.detail}}</span> //将index绑定在span的数据中 </p> </vueSeamless> </section> </template> <script> export default { methods:{ handleSectionClick(e){ let target = e.target; if(target.tagName == "SPAN") { // 2.0、根据事件捕获 捕获目标元素节点,执行点击事件 this.handleDetailClick(target.dataset.id); } }, //3.0、执行点击事件 handleDetailClick(e){ console.log(e) }, } } </script>
保存运行,正常处理了所有span的点击事件
备注
@click.stop与@click.prevent
@click.stop 阻止事件冒泡
@click.prevent 阻止事件的默认行为,
<a href="http://www.baidu.com" @click.prevent="test4">百度一下</a> //阻止a标签跳转,仅执行函数test4
1.给外层div加点击事件,通过event.target
获取到点击的dom元素
获取到event
和 event.target
,如下
获取到了button之后,因为接下来的操作还需要用到ID和name,所以要给button绑定属性
id和name是button自带的属性,vue中自定义属性时还需要添加前缀 data-,获取时要加 dataset
1、定义属性——:data-dept
或 :data-id
2、获取属性——event.target.dataset.dept
或 e.target.dataset.id
可控制台打印数据,进行验证
现在获取到了所有想要的数据 和 要响应的事件,接下来执行事件即可。
代码如下:
<div class="m_tableContent m_gasMonitoring" @click="handleClick($event)"> <div class="m_tableTitle"> <ul> <li>编号</li> <li>员工姓名</li> <li>一氧化碳(ppm)</li> <li>甲烷(%)</li> <li>氧气(%)</li> <li>温度(℃)</li> <li>湿度(%)</li> <li style="width: 30%">地点</li> <li>操作</li> </ul> </div> <vue-seamless-scroll :data="listData" :class-option="classOption" class="seamless-warp"> <ul v-loading="loading" class="item seamless-table"> <li v-for="(item,index) in listData" :key="index" class="seamless-row"> <p class="m_rowItem ">{{ item.sequenceId }}</p> <p class="m_rowItem">{{ item.staffName }}</p> // 部分省略 <p class="m_rowItem"> <button :id="item.staffId" :name="item.staffName" :data-dept="item.deptName" type="danger" class="el-button el-button--danger el-button--mini is-plain" plain size="mini">呼叫</button> </p> </li> </ul> </vue-seamless-scroll> </div> </template> <script> export default { name: 'GasMonitorTable', methods: { handleClick(event) { console.log(event) console.log(event.target) this.staffInfo.staffId = event.target.id this.staffInfo.staffName = event.target.name this.staffInfo.deptName = event.target.dataset.dept this.handlePhoneStaff() } } } </script>
界面
弹框
index.vue
<script lang="ts" setup> import titleHeader from '../header/titleHeader.vue' import img from '@/assets/yfdd-bs/main/left/dqyj.png' import { ref } from 'vue' const dialogVisible = ref(false) const isDialog = (e:any) => { console.log(e) dialogVisible.value = true } const handleSectionClick = (e:any) => { if (e.target.tagName === 'SPAN') { isDialog(e.target.dataset.id) } } const bgImg = ref('bg-dqyj-dialog') const list = ref([ { id: 1, txt: '001中国气象台11月8日10时继续发布橙色预警:请广大一线工作者,注意防风保暖,提前采取防护措施' }, { id: 2, txt: '002中国气象台11月8日10时继续发布橙色预警:请广大一线工作者,注意防风保暖,提前采取防护措施中国气象台11月8日10时继续发布橙色预警:请广大一线工作者,注意防风保暖,提前采取防护措施' } ]) </script> <template> <div class="container" @click="handleSectionClick($event)" > <titleHeader :src="img" :need-line="true" :line-width="[270, 24]" /> <vue3-seamless-scroll :list="list" class="scroll" :limit-scroll-num="1" hover > <div class="item" v-for="(item) in list" :key="item.id" > <!-- <span>{{ item.txt }}</span> --> <div style="width: 100%; height: 200px;overflow:hidden"> <div class="yj-count" > <img style="display:inline-block;margin-left: 40px;margin-bottom:10px" src="@/assets/yfdd-bs/main/left/baoxue.png" alt="" > <div class="yj-fgx" /> <div style="display:inline-block;width: 300px;padding-left:30px;height: 90px;" > <span class="yi-text" :data-id="item.id" > {{ item.txt }} </span> </div> </div> </div> </div> </vue3-seamless-scroll> <el-dialog v-model="dialogVisible" width="1200px" top="120px" :modal="false" :close-on-click-modal="false" :custom-class="bgImg" :lock-scroll="false" > <template #title> <div class="title"> 气象预警 </div> </template> <div class="dialogContent"> <el-row> <el-col :span="12" class="yj-txt" > <span>预警级别:</span> <span style="color: #F0FFF0;font-size: 30px;">三级</span> </el-col> <el-col :span="12" class="yj-txt" > <span>预警类型:</span> <span style="color: #F0FFF0;font-size: 30px;">暴雪天气</span> </el-col> <el-col :span="12" class="yj-txt" > <span>预警来源:</span> </el-col> <el-col :span="24" class="yj-txt" > <span style="color: #F0FFF0; display: inline-block;font-size: 30px;padding-right: 40px;">中央气象台中央气象台中央气象台中央气象台中央气象台中央气象台中央气象台中央气象台中央气象台</span> </el-col> </el-row> </div> </el-dialog> </div> </template> <style lang="scss" scoped> .container{ background-image: url(@/assets/yfdd-bs/main/left/back1.png); background-repeat: no-repeat; background-size: 100% 100%; .scroll { height: 120px; width: 100%; margin: 10px auto; overflow: hidden; } .scroll .item { display: flex; align-items: center; justify-content: space-between; padding: 3px 0; } .yj-count{ border-bottom: 1px solid #14b6f7; margin: 0px 30px 30px 30px; padding-bottom: 20px; .yj-fgx{ height: 70px; display:inline-block; border-right:1px #14b6f7 solid; margin-left:30px; margin-top:10px; margin-bottom:30px; } .yi-text{ display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; height: 124px; font-size:24px } } .dialogContent{ font-size: 20px; } .title{ height: 90px; text-align: center; line-height: 90px; font-weight: 600; color: white; font-size: 26px; } .yj-txt{ color: #fff; font-size: 36px; display: inline-block; padding-left: 40px; margin-top: 30px; } .dialogContent{ font-size: 20px; } .title{ height: 90px; text-align: center; line-height: 90px; font-weight: 600; color: white; font-size: 26px; } .yj-txt{ color: #fff; font-size: 36px; display: inline-block; padding-left: 40px; margin-top: 30px; } :deep(.el-dialog__header){ padding: 0; } :deep(.el-dialog__body) { padding: 0px !important; } } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。