vue封装的可视化滚动表格组件

7,249 阅读1分钟

前言

在大屏数据可视化方面,我们经常会使用到表格组件,这次封装的是不带分页的表格组件,对于长列表表格,我们采用的是滚动轮播的形式向下滚动展示表格数据。组件的翻页滚动是基于 vue-awesome-swiper 二次封装去实现的。 滚动表格组件.gif

1. 安装相应第三方包

装包建议使用cnpm 或者 yarn ,不然速度会很慢

npm install swiper vue-awesome-swiper -S

2. 引入vue-awesome-swiper轮播组件

  • 在main.js中引入相关的第三方组件
import VueAwesomeSwiper from 'vue-awesome-swiper';
import 'swiper/css/swiper.css';
...
Vue.use(VueAwesomeSwiper);

3. 表格组件封装

  • 新建组件文件 image.png
  • 定义组件传入的属性 image.png
  • 定义的组件的数据
    1. currentActiveRow 当前组件表格选中的行数
    2. swiperOption 相关定义滚动轮播参数,具体可参考 vue-awesome-swiper
data() {
    return {
      currentActiveRow: 0,
      swiperOption: {
        autoHeight: true,
        direction: 'vertical',
        spaceBetween: 0,
        autoplay: {
          delay: 2500,
          disableOnInteraction: false,
          autoplayDisableOnInteraction: false
        },
        slidesPerView: 'auto',
        grabCursor: true,
        autoplayDisableOnInteraction: false,
        mousewheelControl: true
      }
    };
  },
  • 模板页的编写
<template>
  <div
    class="table-wrapper"
    :style="{
      width: 'calc(' + widths.reduce((i, j) => `${i} + ${j}`) + ` + ${(widths.length - 1) * 6}px)`,
      height: `calc(${contentHeight} + 48px)`
    }"
  >
    <div class="table-header" v-if="showHeader">
      <span v-for="(it, i) in widths" :key="i" :style="{ width: widths[i] }">{{ titles[i] }}</span>
    </div>
    <div class="table-content" :style="{ height: contentHeight }">
      <swiper class="swiper" :options="swiperOption" ref="myBotSwiper">
        <swiper-slide v-for="(it, i) in dataList" :key="i">
          <div
            class="table-row"
            :class="{ stripe: i % 2 === 1, active: i === currentActiveRow }"
            @click="handleRowClick(it, i)"
            :style="{ height: tabelHeight }"
          >
            <span
              v-for="(ite, ind) in widths"
              :key="ind"
              :title="it[ind]"
              :style="{ width: widths[ind], height: tabelHeight }"
              >{{ it[ind] }}</span
            >
          </div>
        </swiper-slide>
      </swiper>
    </div>
  </div>
</template>

4. 表格组件的点击监听

  • 在父类组件传入 change 事件,组件内点击触发
  • 如果 需要点击表格的行数据时 不让表格滚动,就相应的调用 swiperStop 方法;swiperStart 从当前开始滚动
methods: {
    handleRowClick(it, i) {
      this.currentActiveRow = i;
      const currentIt = this.data[i];
      this.$emit('change', currentIt);
    },
    // 控制表格停止滚动
    swiperStop() {
      this.myBotSwiper.autoplay.stop();
    },
    // 控制表格开始滚动
    swiperStart() {
      this.myBotSwiper.autoplay.start();
    }
  },

5. 组件的使用方式示例

image.png

6. 组件完整代码

<template>
  <div
    class="table-wrapper"
    :style="{
      width: 'calc(' + widths.reduce((i, j) => `${i} + ${j}`) + ` + ${(widths.length - 1) * 6}px)`,
      height: `calc(${contentHeight} + 48px)`
    }"
  >
    <div class="table-header" v-if="showHeader">
      <span v-for="(it, i) in widths" :key="i" :style="{ width: widths[i] }">{{ titles[i] }}</span>
    </div>
    <div class="table-content" :style="{ height: contentHeight }">
      <swiper class="swiper" :options="swiperOption" ref="myBotSwiper">
        <swiper-slide v-for="(it, i) in dataList" :key="i">
          <div
            class="table-row"
            :class="{ stripe: i % 2 === 1, active: i === currentActiveRow }"
            @click="handleRowClick(it, i)"
            :style="{ height: tabelHeight }"
          >
            <span
              v-for="(ite, ind) in widths"
              :key="ind"
              :title="it[ind]"
              :style="{ width: widths[ind], height: tabelHeight }"
              >{{ it[ind] }}</span
            >
          </div>
        </swiper-slide>
      </swiper>
    </div>
  </div>
</template>

<script>
export default {
  name: 'swiper-table',
  props: {
    // 传入的表格数据
    data: {
      type: Array,
      default: () => [
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ],
        [
          '杂草乱扔',
          '2020.08.23 12:26:15',
          '全要素网格化',
          '公安交警',
          '环境保护',
          '待受理',
          '李念省'
        ]
      ]
    },
    // 传入的表格头
    titles: {
      type: Array,
      default: () => ['事件标题', '创建时间', '信息来源', '分类', '状态', '上报人']
    },
    // 表格的列宽
    widths: {
      type: Array,
      default: () => ['246px', '348px', '224px', '214px', '214px', '214px']
    },
    // 表格的高度
    contentHeight: {
      type: String,
      default: '356px'
    },
    // 是否展示表格头
    showHeader: {
      type: Boolean,
      default: true
    },
    // 表格的行高
    tabelHeight: {
      type: String,
      default: '36px'
    }
  },
  computed: {
    myBotSwiper() {
      return this.$refs.myBotSwiper.$swiper;
    }
  },
  data() {
    return {
      currentActiveRow: 0,
      swiperOption: {
        autoHeight: true,
        direction: 'vertical',
        spaceBetween: 0,
        autoplay: {
          delay: 2500,
          disableOnInteraction: false,
          autoplayDisableOnInteraction: false
        },
        slidesPerView: 'auto',
        grabCursor: true,
        autoplayDisableOnInteraction: false,
        mousewheelControl: true
      }
    };
  },
  methods: {
    handleRowClick(it, i) {
      this.currentActiveRow = i;
      const currentIt = this.data[i];
      this.$emit('change', currentIt);
    },
    // 控制表格停止滚动
    swiperStop() {
      this.myBotSwiper.autoplay.stop();
    },
    // 控制表格开始滚动
    swiperStart() {
      this.myBotSwiper.autoplay.start();
    }
  },
  watch: {
    data() {
      this.currentActiveRow = 0;
    }
  }
};
</script>

<style lang="scss" scoped>
.table-wrapper {
  width: 100%;
  height: 497px;
  span {
    box-sizing: border-box;
  }
  .table-header {
    $height: 31px;
    width: 100%;
    height: $height;
    span {
      color: #83c2ee;
      //   background: rgba(255, 255, 255, 0.12);
      background-color: #013558;
      font-size: 19px;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: rgba(131, 194, 238, 1);
      line-height: $height;
      &:nth-child(2) {
        text-align: center;
      }
    }
    span + span {
      margin-left: 2px;
    }
  }
  .table-content {
    width: 100%;
    height: 284px;
    margin-top: 2px;
    .swiper {
      width: 100%;
      height: 100%;
      .table-row {
        width: 100%;
        height: 36px;
        cursor: pointer;
        &.active {
          span {
            color: rgba(131, 194, 238, 1);
            font-size: 17px;
            font-weight: bold;
          }
        }
        &.stripe span {
          background: rgba(255, 255, 255, 0.06);
        }
        span {
          font-size: 17px;
          font-family: PingFangSC-Regular, PingFang SC;
          font-weight: 400;
          color: rgba(255, 255, 255, 0.85);
          line-height: 36px;
        }
        span + span {
          margin-left: 2px;
        }
      }
    }
  }
  span {
    height: 100%;
    line-height: 100%;
    display: inline-block;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: 6px;
    &:nth-child(1) {
      width: 246px;
    }
    &:nth-child(2) {
      width: 348px;
      padding-left: 13px;
    }
    &:nth-child(3) {
      width: 214px;
    }
    &:nth-child(4) {
      width: 214px;
    }
    &:nth-child(5) {
      width: 214px;
    }
  }
}
</style>

码字不易,欢迎大家批评指导,互相学习。觉得好请点个赞。