前言

如果项目使用了elementUI,可以看一下。如果没有使用,可以看我的另一篇文章,用div写的滚动表格
项目看板滚动数据显示。

参考文章:Element动态生成表格以及表格内容无缝滚动

感谢这篇文章的思路,开阔了思路。

指令版

需求(功能)

  • 数据按条滚动
  • 支持自定义列内容
  • 设置表格背景色和字体颜色

本来还想加个鼠标移入停止,移出重新滚动的功能,但是指令里没法监听。这个功能就没法实现

效果图

element ui table 显示滚动条 element表格滚动_javascript


实现代码

let value = (el, binding) => {
  //console.log("表格:", el);

  //默认参数
  let defaultOptions = {
    //页面最多显示的行数
    maxNumner: 4,
    //滚动速度(毫秒)
    speed: 1500,
    //数据总条数,默认5
    totalNumber: 5,
    //是否滚动,默认滚动
    isScroll: true,
    //背景色
    background: "#FFFFFF",
    //字体颜色
    color: "#909399",
  };

  //参数处理
  let options = Object.assign(defaultOptions, binding.value);

  //获取表格头部
  let elHeader = el.getElementsByClassName("has-gutter")[0];

  //设置表头背景色和字体颜色(可以多级)
  for (let tr of elHeader.childNodes) {
    for (let th of tr.childNodes) {
      th.style.background = options.background;
      th.style.color = options.color;
    }
  }

  //elHeader.style.background = "blue";

  //获取el-table表格的容器,如果class变了,可能会出问题
  let elwrapper = el.getElementsByClassName("el-table__body-wrapper")[0];
  //console.log("容器:", elwrapper);

  //设置容器高度,50固定不要随意修改
  elwrapper.style.height = options.maxNumner * 50 + "px";

  //获取表格主体
  let elBody = elwrapper.getElementsByClassName("el-table__body")[0];

  //获取每一行
  let elRow = elBody.getElementsByClassName("el-table__row");

  //设置行高,默认50不要修改,试过自定义有些问题
  for (let node of elRow) {
    node.style.height = 50 + "px";
    //设置表格的颜色
    node.style.background = options.background;
    //设置字体颜色
    node.style.color = options.color;
  }

  //设置滚动样式
  elBody.style.position = "absolute";
  elBody.style.transition = "all 500ms linear";

  //设置过度时间
  elBody.style.transactionDuration = "500ms";

  //初始化窗口位置
  elBody.style.top = 0;

  //定时器,标识
  let mark = undefined;

  //当前所在行
  let active = 0;
  if (options.isScroll) {
    //当页面显示的行数小于总条数时滚动
    if (options.maxNumner < options.totalNumber) {
      mark = setInterval(() => {
        if (active < options.totalNumber) {
          active += 1;
          elBody.style.top = parseInt(elBody.style.top) - 17 + "px";
        } else {
          active = 0;
          elBody.style.top = 0;
        }
      }, options.speed);
    }
  } else {
    window.clearInterval(mark);
  }
};
export default {
  name: "roll",
  mounted: value,
  updated: value,
};

使用

<template>
  <div >
    <el-table :data="tableData" style="width: 100%" border v-roll="options">
      <el-table-column prop="date" label="Date" width="180" />
      <el-table-column prop="name" label="Name" width="180" />
      <el-table-column prop="address" label="Address" />
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          date: "2016-05-03",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
        {
          date: "2016-05-02",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
        {
          date: "2016-05-04",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
        {
          date: "2016-05-01",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
         {
          date: "2016-05-01",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
         {
          date: "2016-05-01",
          name: "Tom",
          address: "No. 189, Grove St, Los Angeles",
        },
      ],
      //滚动配置项
      options:{
          totalNumber:6,
          isScroll:true,
          background:'#2B9ACA',
          color:'#000000'
      }
    };
  },
  mounted() {},
  methods: {
  },
};
</script>

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

组件版

实现代码

<template>
    <div
        @mouseover="stopSrcoll"
        @mouseout="startSrcoll"
        @mousewheel="handleWheel">
        <el-table :data="tableData" :border="showBorder" style="width: 100%" ref="everTable"
                  :header-cell-style="headerStyle" :cell-style="cellStyle">
            <slot></slot>
        </el-table>
    </div>
</template>

<script>
export default {
    name: 'DtSrcoll',
    props: {
    // 表格主体
        tableData: {
            type: Array,
            default: () => []
        },
        // 是否显示边框
        showBorder: {
            type: Boolean,
            default: false
        },
        lineHeight: {
            // 页面需要显示的行数
            type: Number,
            default: 4
        },
        rowTime: {
            // 每一行滚动切换等待的时间(毫秒)
            type: Number,
            default: 1500
        },
        duration: {
            // 过渡时间
            type: Number,
            default: 500
        },
        tableHeight: {
            // 行高
            type: Number,
            default: 50
        },
        isClear: {
            // 数据滚动到最后一行是否停止滚动
            type: Boolean,
            default: false
        },
        isAgain: {
            // 数据滚动到最后一行是否重新开始滚动
            type: Boolean,
            default: true
        },
        isScroll: {
            // 是否允许内容滚动
            type: Boolean,
            default: true
        },
        headerStyle: {
            // 表头样式
            type: [Object,Function]
        },
        cellStyle: {
            // 单元格样式
            type: [Object,Function]
        }
    },
    data() {
        return {
            // 标识
            active: 0,
            // 定时器
            timer: '',
            // 容器
            elwrapper: undefined
        };
    },
    mounted() {
        this.startSrcoll();
    },
    methods: {
    // 开始滚动
        startSrcoll() {
            let _this = this;
            // console.log(this.$refs.everTable.$el);
            let everTable = this.$refs.everTable.$el;
            this.$nextTick(() => {
                let elwrapper = everTable.getElementsByClassName(
                    'el-table__body-wrapper'
                )[0];

                this.elwrapper = elwrapper;

                let elBody = everTable.getElementsByClassName('el-table__body')[0];
                _this.elBody = elBody;

                elBody.style.position = 'absolute';
                elBody.style.transition = 'all 500ms linear';

                setTimeout(() => {
                    let elRow = everTable.getElementsByClassName('el-table__row');
                    for (let node of elRow) {
                        node.style.height = _this.tableHeight + 'px';
                    }
                    elwrapper.style.height = _this.lineHeight * _this.tableHeight + 'px';
                },1000);

                elBody.style.top = 0;

                elBody.style.transactionDuration = this.duration + 'ms';

                if (_this.isScroll) {
                    _this.timer = setInterval(function () {
                        if (
                            _this.active <
              parseInt(_this.tableData.length) - parseInt(_this.lineHeight)
                        ) {
                            _this.active += 1;
                            elBody.style.top =
                parseInt(elBody.style.top) - parseInt(_this.tableHeight) + 'px';
                        } else {
                            if (this.isClear) {
                                clearInterval(this.timer);
                            }
                            if (_this.isAgain) {
                                _this.active = 0;
                                elBody.style.top = 0;
                            } else {
                                clearInterval(_this.timer);
                            }
                        }
                    }, _this.rowTime);
                }
            });
        },
        // 停止滚动
        stopSrcoll() {
            clearInterval(this.timer);
        },
        // 处理滑轮事件
        handleWheel(e) {
            //  console.log('容器:',this.elwrapper);
            // 负加正减
            if(e.wheelDeltaY < 0) {
                this.elwrapper.scrollTop += 10;
            }else{
                this.elwrapper.scrollTop -= 10;
            }

            // console.log(this.elwrapper.scrollTop);
        }
    },
    destroyed() {
        clearInterval(this.timer);
    }
};
</script>

<style lang="scss" scoped>

</style>

使用

<template>
  <div style="height: 100%; width: 98%; margin: 0 1%">
    <dt-srcoll showBorder :tableData="dutyRateData">
      <el-table-column label="序号" type="index" width="60" align="center"></el-table-column>
      <el-table-column prop="date" label="Date" min-width="180" align="center" />
      <el-table-column prop="name" label="Name" min-width="180" align="center" />
      <el-table-column label="Address" align="center" >
        <el-table-column
          prop="country"
          label="国家"
          min-width="180"
          align="center"
        />
        <el-table-column
          prop="provience"
          label="省"
          min-width="180"
          align="center"
        />
      </el-table-column>
    </dt-srcoll>
  </div>
</template>

<script>
import dtSrcoll from "@/views/yc/test/roll-table/dt-srcoll";
export default {
  components: { dtSrcoll },
  data() {
    return {
      dutyRateData: [
        {
          date: "2016-05-03",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
        {
          date: "2016-05-02",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
        {
          date: "2016-05-04",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
        {
          date: "2016-05-01",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
          {
          date: "2016-05-04",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
        {
          date: "2016-05-01",
          name: "Tom",
          country: "中国",
          provience: "山东",
        },
      ],
    };
  },
  mounted() {},
  methods: {},
};
</script>

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

关于表格背景色和字体颜色的问题:
最初是加了两个props属性,background:背景色,color:字体颜色。但是有两个致命的点

  • 表头可以正常渲染,但是关于表格的行,不会渲染。原因是行是动态生成的,第一次渲染时没有获取到dom,后来加了个延时函数,可以正常渲染出来但是会出现一个闪烁。实现如下:
// 设置表头背景色和字体颜色(可以多级)
 let elHeader = document.getElementsByClassName('has-gutter')[0];
 for (let tr of elHeader.childNodes) {
     for (let th of tr.childNodes) {
         th.style.background = _this.background;
         th.style.color = _this.color;
     }
 }

//设置表格主体
setTimeout(() => {
    let elRow = document.getElementsByClassName('el-table__row');
    for (let node of elRow) {
        node.style.height = _this.tableHeight + 'px';
        // 设置表格的颜色
        node.style.background = _this.background;
        // 设置字体颜色
        node.style.color = _this.color;
    }
}, 100);
  • 最致命的是上面那种形式,实现的样式比较单一。如果你有比较特别的样式需求,比如我需要的样式就比较特别。最后只能使用element-table自身提供的实现形式

关于表格和单元哥样式的设置,以及表格的其他用法,可以看我的这篇文章

element——table表格常用点

注:如果要改变表头和表格的颜色,可能还需要改一下表格的整体颜色,如下:

/deep/ .el-table{
    background: rgb(9, 24, 79);
}