• vue 基于vue-seamless-scroll无缝滚动的用法和遇到的问题解决


    vue 基于vue-seamless-scroll无缝滚动的用法和遇到的问题解决

    背景

    最近再做一个大屏项目,需要用到表格滚动效果,之前自己写过js实现,最近发现一个组件vue-seamless-scroll可以实现滚动,感觉挺方便的,准备用一下,但是用完之后才发现这个组件有很多坑需要解决.我把用法和一些问题的解决方法记录一下.

    需求

    实现表格滚动效果,表格中过长的是文字需要悬停展示,点击每行弹出详情弹框,数据每分钟更新一次.

    安装vue-seamless-scroll

    npm install vue-seamless-scroll --save  
    
    • 1

    引入组件

    
     
    import vueSeamlessScroll from 'vue-seamless-scroll'
     
    components: {
            vueSeamlessScroll
    }, 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    配置参数

    // 监听属性 类似于data概念
            computed: {
                defaultOption () {
                    return {
                        step: 0.2, // 数值越大速度滚动越快
                        limitMoveNum: 2, // 开始无缝滚动的数据量 this.dataList.length
                        hoverStop: true, // 是否开启鼠标悬停stop
                        direction: 1, // 0向下 1向上 2向左 3向右
                        openWatch: true, // 开启数据实时监控刷新dom
                        singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
                        singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
                        waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
                    }
                }
     
            },  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    上边的安装使用很简单,大家可以官方文档看看.
    刚开始我还觉得这个组件很好用,可是后来现实改变了我的想法.

    遇到的问题

    我把项目代码放上,便于下边问题描述,这是最终代码

    html
    {{item.title}}
    {{item.caseLevel}}
    {{getCaseType(item.caseType)}}
    {{formatDate(item.receiveCaseTime)}}
    {{item.caseSummary}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    js
    data() {
        return {
          headerList: [
            { id: 1, title: '级别', className: 'caseLevel', width: 60 },
            { id: 2, title: '类型', className: 'caseType', width: 100 },
            { id: 3, title: '时间', className: 'receiveCaseTime', width: 100 },
            { id: 4, title: '概要', className: 'caseSummary', width: 130 }
          ],
          classOption: {
            direction: 1, //滚动方向
            step: 0.5, //滚动速度  越打越快
            singleHeight: 28, //滚动距离
            limitMoveNum: 6
          },
        }
      },
    ...
    clickHang($event) {
          if ($event.target.dataset) {
            const item = JSON.parse($event.target.dataset.obj)
            console.log(item )
            //去打开弹框
          }
        },
        handleMouseover(el) {
          //判断el是否在content的``标签上
          if (el.target.className.includes('table-content')) {
            el.target.style.cursor = 'pointer'
            //el所在div的transform在y轴上的移动px
            let h = parseFloat(
              this.$refs['tableCont'].parentElement.parentElement.style.transform
                .replaceAll('translate(0px,', '')
                .replace('px)', '')
            )
            //显示div
            this.$refs['vc-tooltip'].style.display = ''
            this.$refs['vc-tooltip'].innerHTML = el.target.innerHTML
            this.$refs['vc-tooltip'].style.left = el.target.offsetLeft - this.$refs['vc-tooltip'].offsetWidth / 2 + 'px'
            //判断el所在的div后面是否有元素,有则为第一个div
            // if (el.target.parentElement.parentElement.parentElement.nextSibling != null) {
            this.$refs['vc-tooltip'].style.top = el.target.offsetTop + h - 10 + 'px'
            // } else {
            //   //当el所在div为第二个即最后一个,弹窗的top还需加上上一个div的高度
            //   this.$refs['vc-tooltip'].style.top =
            //     el.target.offsetTop + h + this.$refs['tableCont'].offsetHeight - 10 + 'px'
            // }
          }
        },
        handleMouseout(el) {
          if (el.target.className.includes('table-content')) {
            this.$refs['vc-tooltip'].style.display = 'none'
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    css

    .table_box {
          margin: 5px;
          text-align: center;
          position: relative;
          .heared {
            display: flex;
            height: 21px;
            line-height: 21px;
            align-items: center;
            justify-content: space-between;
            background-color: rgba(6, 90, 254, 0.8);
            & > div {
              margin-left: 5px;
              font-family: Noto Sans SC;
              font-size: 16px;
              font-weight: 700;
              color: #fccd1d;
            }
          }
          .scrollBox {
            .tooltip-box {
              z-index: 5;
              background: #303133;
              color: #fff;
              padding: 10px;
              line-height: 1.2;
              min-width: 10px;
              word-wrap: break-word;
              border-radius: 4px;
              font-size: 12px;
            }
          }
          .warp {
            height: 146px;
            overflow: hidden;
            // margin: 10px 0;
          }
          .tableCont {
            .hangBox {
              height: 27px;
              pointer-events: all;
              padding-top: 1px;
            }
            .hang {
              display: flex;
              align-items: center;
              justify-content: space-between;
              margin-top: 9px;
              height: 18px;
              line-height: 18px;
              font-style: normal;
              font-size: 16px;
              color: #ffffff;
              background-color: rgba(6, 90, 254, 0.5);
              font-family: Noto Sans SC;
              pointer-events: none;
              & > div {
                margin-left: 5px;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                .table-content {
                  pointer-events: all;
                }
              }
              .caseLevel {
                width: 60px;
              }
              .receiveCaseTime {
                width: 100px;
              }
              .caseType {
                width: 100px;
              }
              .caseSummary {
                width: 130px;
              }
            }
          }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    1.每一行挂载点击事件

    开始的思路是在表格行上添加@click事件就行了,这种方式不可行,发现有的行点击事件挂载不上,后来看了看,明白了大概原因,
    由于插件为了实现无缝滚动的效果会把表格html部分复制一份,用于滚动的衔接,但是复制的部分不会挂载点击事件.

    解决方法

    思路:在每一行中添加属性值, :data-obj=“JSON.stringify(item)”,再通过外层的点击事件clickHang,获取目标元素的属性值.

    这里还会引发一个问题的是:
    如果每一行中的元素结构比较复杂,:data-obj="JSON.stringify(item)"挂载的位置需要考虑一下,如果挂错地方了,外层点击事件获取不到属性值.
    这里我使用css属性把hangBox中hang属性pointer-events: none;然后把hangBox元素设置pointer-events: all;目的就是只留下hangbox的触发事件,内部元素就不会影响了.

    2.表格中每一行过长,悬停提示

    开始思路是直接用elementui中组件el-tooltip实现,但是又遇到问题了,还是上边的问题,插件把表格html部分复制的部分不会有提示.

    解决方法

    思路:在外边写个弹框,在组件上挂上,mouseover,mouseout事件,通过鼠标事件控制弹框的显隐,代码在上边大家可以去看看.
    这里也遇到了一个问题
    由于上边为了解决行点击事件,准确获取每行数据问题,咱们把.hang元素的属性pointer-events: none;导致hang中的元素触发不了悬停,所以得把里边的table-content元素属性设置成pointer-events: all;在这个元素上挂上属性:data-obj=“JSON.stringify(item)”,这样完美解决了.

    希望对你有帮助,虽然这个组件使用中出现了好多问题,但是对于只实现滚动的需求,这个组件还是很好用的

  • 相关阅读:
    Java基础之《netty(6)—NIO快速入门》
    【不良事件上报源码】医疗安全(不良)事件管理系统
    CentOS7 安装 ElasticSearch7.10
    剑指offer 49. 最长不含重复字符的子字符串
    游戏开发应该关注质量而不是数量
    中国核动力研究设计院使用 DolphinDB 替换 MySQL 实时监控仪表
    PLSQL下载并安装
    SpringBoot启动的时候做了什么(1)
    LaTeX 010:让 texify 支持 Biber
    内存池的实现4 alloc内存池
  • 原文地址:https://blog.csdn.net/weixin_46995731/article/details/133375813