vue2实现列表、表格超出高度滚动,鼠标移入移出事件

大屏页面需要实现内容超出时列表滚动,没有超出则不滚动,通过一下写法实现,页面滚动在多次加载或者移入移出时抖动明显且内容闪烁

ul.style.transform = `translateY(${offsetY}px)`

所以使用vue-seamless-scroll实现
第一步安装

 npm install vue-seamless-scroll --save

第二步页面使用如下

<vue-seamless-scroll
     :data="liList"
     class="seamless-warp"
     :class-option="classOption"
>
     <ul style="overflow: hidden" ref="origin_chongzhuang">
         <li
            v-for="(item, index) in liList"
            :key="index"
            :title="item.pointName + item.pointValue"
          >
             <p>{{ item.pointName }}</p>
             <p>{{ item.pointValue }}</p>
          </li>
      </ul>
 </vue-seamless-scroll>
 import VueSeamlessScroll from "vue-seamless-scroll";
 export default {
  components: { VueSeamlessScroll },
  computed: {
    classOption() {
      return {
        step: 0.4, // 数值越大速度滚动越快
        limitMoveNum: 5, // 当数据量小于这个值时,不滚动
        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)
      };
    },
  },
 }

vue2 element的table组件实现表格自滚动,鼠标移入停止滚动、移出继续滚动、滚动到底部时触发加载更多功能

父组件:

<template>
  <!-- 告警信息 -->
  <div style="height: 100%">
    <generalTables
      ref="generalTables"
      v-if="loading"
      :tableList="tableList"
      :columnList="columnList"
      @handleScroll="handleScroll"
      height="38vh"
    ></generalTables>
    <dv-loading v-else>加载中...</dv-loading>
  </div>
</template>

<script>
import { warningInfo } from "@/api/mes/screen";
import generalTables from "../generalTables.vue";
export default {
  components: {
    generalTables,
  },
  data() {
    return {
      loading: false,
      tableList: [],
      columnList: [
        {
          label: "名称",
          prop: "Name",
        },
        {
          label: "种类",
          prop: "Species",
        },
        {
          label: "内容",
          prop: "Content",
          type: "waring",
        },
        {
          label: "时间",
          prop: "Time",
          type: "time",
        },
      ],
      total: 0,
      query: {
        pageNum: 1,
        pageSize: 10,
      },
    };
  },
  created() {
    this.loading = false;
    this.getWarningInfo();
  },
  methods: {
    getWarningInfo() {
      warningInfo(this.query).then((res) => {
        this.loading = true;
        this.total = res.total;
        this.tableList = [...this.tableList, ...res.rows];
      });
    },
    handleScroll() {
      if (this.tableList.length < this.total) {
        this.query.pageNum++;
        this.getWarningInfo();
      } else {
        this.$refs.generalTables.resetScroll();
      }
    },
  },
};
</script>

<style lang="scss" scoped></style>

子组件:

<template>
  <div
    class="stripeTable"
    @mouseenter="stopAutoScroll"
    @mouseleave="startAutoScroll"
  >
    <el-table
      ref="table"
      :data="tableList"
      :show-header="showHeader"
      :height="height"
      @scroll.passive="handleScroll"
    >
      <el-table-column
        align="center"
        label="序号"
        :width="String(innerWidth * 0.03)"
      >
        <template slot-scope="scope">
          <span>{{ scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <el-table-column
        v-for="(item, index) in columnList"
        show-overflow-tooltip
        align="center"
        :key="index"
        :prop="item.prop"
        :width="item.width ? String(innerWidth * item.width) : item.width"
        :label="item.label"
      >
        <template slot-scope="scope">
          <span v-if="item.type == 'time'">{{
            scope.row[item.prop]
              ? parseTime(scope.row[item.prop], "{y}-{m}-{d}")
              : "-"
          }}</span>
          <span v-else-if="item.type == 'dict'">
            <dict-tag
              :options="dict.type.production_status"
              :value="scope.row[item.prop]"
              :isTag="true"
            />
          </span>
          <span
            v-else-if="item.type == 'percentage'"
            :style="{ color: scope.row[item.prop] ? '#0bffb2' : '#fff' }"
          >
            {{ scope.row[item.prop] ? scope.row[item.prop] + "%" : "-" }}
          </span>
          <span
            v-else-if="item.type == 'hours'"
            :style="{ color: scope.row[item.prop] ? '#0bffb2' : '#fff' }"
          >
            {{ scope.row[item.prop] || "-" }}
          </span>
          <span
            v-else-if="item.type == 'error'"
            :style="{
              color: scope.row[item.prop]
                ? scope.row[item.prop] >= 60
                  ? '#FF7124'
                  : '#FFAE4A'
                : '#fff',
            }"
          >
            {{ scope.row[item.prop] ? scope.row[item.prop] + "%" : "-" }}
          </span>
          <span v-else>{{ scope.row[item.prop] || "-" }}</span>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import { debounce } from "@/utils";
export default {
  dicts: ["production_status"],
  props: {
    tableList: {
      type: Array,
      default: () => [],
    },
    showIndex: {
      type: Boolean,
      default: true,
    },
    columnList: {
      type: Array,
      default: () => [],
    },
    showHeader: {
      type: Boolean,
      default: true,
    },
    height: {
      type: String,
      default: "18vh",
    },
  },
  data() {
    return {
      innerWidth: 1920,
      scrollInterval: null,
      scrollStep: 1, // 滚动步长
      scrollSpeed: 100, // 滚动速度(毫秒)
    };
  },
  mounted() {
    this.innerWidth = window.innerWidth;
    addEventListener("resize", debounce(this.widthScroll, 200));
    const scrollBody = this.$refs.table.$el.querySelector(
      ".el-table__body-wrapper"
    );
    scrollBody?.addEventListener("scroll", this.handleScroll);
    this.startAutoScroll();
  },
  beforeDestroy() {
    this.stopAutoScroll()
    const scrollBody = this.$refs.table.$el.querySelector(
      ".el-table__body-wrapper"
    );
    scrollBody?.removeEventListener("scroll", this.handleScroll);
    window.removeEventListener("resize", this.debouncedWidthScroll); // 移除 resize 事件监听器
  },
  methods: {
    widthScroll() {
      this.innerWidth = window.innerWidth;
    },
    handleScroll(event) {
      const { scrollTop, scrollHeight, clientHeight } = event.target;
      if (scrollHeight - scrollTop - clientHeight <= 10) {
        this.loadMoreData();
      }
    },
    loadMoreData() {
      this.$emit("handleScroll");
    },
    autoScroll() {
      const scrollBody = this.$refs.table.$el.querySelector(
        ".el-table__body-wrapper"
      );
      if (scrollBody) {
        scrollBody.scrollTop += this.scrollStep;
      }
    },
    startAutoScroll() {
      if (this.scrollInterval) return;
      this.scrollInterval = setInterval(this.autoScroll, this.scrollSpeed);
    },
    stopAutoScroll() {
      if (this.scrollInterval) {
        clearInterval(this.scrollInterval);
        this.scrollInterval = null;
      }
    },
    resetScroll() {
      const scrollBody = this.$refs.table.$el.querySelector(
        ".el-table__body-wrapper"
      );
      if (scrollBody) {
        scrollBody.scrollTop = 0; // 重置滚动位置
      }
      this.startAutoScroll(); // 重新开始自动滚动
    },
  },
};
</script>

<style lang="scss">
.stripeTable {
  .el-table {
    background: none;
    color: #fff;
  }
  .el-table::before {
    height: 0px;
  }

  .el-table thead {
    background: #003360;
  }

  .el-table tr {
    background: none;
    td {
      border-bottom: none;
    }
  }
  .el-table .el-table__row {
    font-size: 0.7vw;
  }

  .cell .el-tooltip {
    height: 100px;
  }
  .el-table td.el-table__cell {
    padding: 0.8vh 0;
  }

  .el-table th.el-table__cell {
    padding: 0.8vh 0;
    font-size: 0.7vw;
  }

  .has-gutter {
    background: #003360 !important;
  }

  .el-table th {
    color: #fff;
  }
  .el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
    color: #5f8fe7;
    background: none !important;
  }
  .el-table th.el-table__cell.is-leaf {
    border-bottom: none;
  }
  .el-table th.el-table__cell {
    background: none !important;
  }
  .el-table__header-wrapper,
  .el-table__body-wrapper {
    margin-bottom: 0 !important;
  }

  // 设置滚动条的宽度
  .el-table__body-wrapper::-webkit-scrollbar {
    width: 0px;
    height: 0;
  }
  // 设置滚动条的背景色和圆角
  .el-table__body-wrapper::-webkit-scrollbar-thumb {
    background-color: #5f8fe7;
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
  }

  .el-table .cell {
    line-height: inherit;
  }

  .el-table th.gutter {
    display: none;
    width: 0;
    height: 0;
  }
  .el-table colgroup col[name="gutter"] {
    display: none;
    width: 0;
    height: 0;
  }
  .el-table__body {
    width: 100% !important;
  }

  .el-table__row:nth-child(2n) {
    background: #003360;
  }
}
</style>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值