vue 开发间隔式自动滚动组件

项目需求千奇百怪,只能尽其所能实现一二。

因开发vue前端,故此次使用vue开发一个间隔式自动滚动组件,代码如下

<template>
    <div id="autoScrll"></div>
</template>

<script>
export default {
    name: 'autoScroll',
    props: {
        ele: HTMLDivElement,// 滚动容器dom元素    必填
        step: {             // 步进值 正数  非必填 默认 10
            type: Number,
            default: 10
        },
        interval: {         // 距下一次滚动时间间隔  单位ms 非必填 默认1000ms
            type: Number,
            default: 1000
        },
        mode: {             // 滚动模式 1:按步进值(step)跳跃式滚动, 2:按照步进值(step)动画方式滚动
            type: Number,
            default: 1
        },
        speed: {            // 模式2 下可设置滚动速度
            type: Number,
            default: 25
        }
    },
    data() {
        return {
            scrollStep: 0,              // 由于props中的值不能直接修改,在data中再声明一个变量,用于动态的修改步进值
            stopScrollTopFlag: false,
            stTimeout: undefined,
            stInterval: undefined,
            slTimeout: undefined,
            slInterval: undefined
        }
    },
    methods: {
        autoScrollTop() {
            if (this.ele) {
                if (!this.scrollStep) {
                    if (!this.step || isNaN(this.step)) this.scrollStep = 10;
                    else this.scrollStep = this.step
                }
                if (!this.interval || isNaN(this.interval)) this.interval = 1000;
                if (this.scrollStep  < 10 || !this.mode) mode = 1;

                const hh = this.ele.offsetHeight;
                const hh2 = this.ele.scrollHeight;
                
                if (hh2 > hh) {
                    let i = 0;
                    let ss = 0;
                    let scroll = this.ele.scrollTop;
                    if (scroll <= 0 || scroll >= (hh2 - hh)) {
                        scroll = 0;
                    } else {
                        i = (scroll / this.scrollStep ) + (scroll % this.scrollStep  == 0 ? 0 : 1);
                        if ((this.scrollStep  * i) >= (hh2 - hh)) {
                            if (scroll % this.scrollStep  == 0) {
                                i = 0;
                                scroll = 0;
                            } else {
                                ss = (this.scrollStep  * i) - scroll;
                                scroll = this.scrollStep  * i;
                            }
                        }
                    }

                    if (this.mode == 1) {
                        // 开始滚动 每次步进滚动一个step高度
                        this.stInterval = setInterval(() => {
                            this.ele.scrollTop = scroll;
                            if ((hh + scroll) >= hh2) {
                                scroll = 0;
                            } else {
                                scroll += this.scrollStep ;
                            }
                        }, this.interval);

                    } else if (this.mode == 2) {
                        this.scrollToTop(hh, hh2, i, scroll - ss);
                    }
                }
            }
        },
        scrollToTop(hh, hh2, i, scroll) {
            let interval2 = setInterval(() => {
                if (!this.stopScrollTopFlag) {
                    this.ele.scrollTop = scroll;
                    if ((hh + scroll) >= hh2) {
                        i = 0;
                        scroll = 0;
            
                        clearInterval(interval2);
                        this.stTimeout = setTimeout(() => {
                            if (!this.stopScrollTopFlag) {
                                this.scrollToTop(hh, hh2, i, scroll);
                                this.stopScrollTop();
                            } else {
                                this.stopScrollTop();
                            }
                        }, this.interval);
                    } else if (scroll >= (this.scrollStep  * i)) {
                        i++;
            
                        clearInterval(interval2);
                        this.stTimeout = setTimeout(() => {
                            if (!this.stopScrollTopFlag) {
                                this.scrollToTop(hh, hh2, i, scroll);
                                this.stopScrollTop();
                            } else {
                                this.stopScrollTop();
                            }
                        }, this.interval);
                    } else {
                        scroll += 2;
                    }
                } else {
                    clearInterval(interval2);
                }
            }, this.speed);
        },
        stopScrollTop () {
            if (this.stTimeout) {
                clearTimeout(this.stTimeout);
                this.stTimeout = undefined;
            }
            if (this.stInterval) {
                clearInterval(this.stInterval);
                this.stInterval = undefined;
            }
        }
    }
}
</script>
View Code

这里在之前写好的table表格组件中引用,实现表格的自动滚动效果,代码如下:

<template>
  <div>
    <div class="table-head">
      <table class="layui-table" style="">
        <colgroup>
          <col v-for="(colItem, idx) in cols" :key="'col-' + idx" :style="{width: getColWidth(colItem)}"/>
        </colgroup>
        <thead>
          <tr>
            <th 
            v-for="(colItem, idx2) in cols" 
            :key="'th-' + idx2" 
            :style="{textAlign: getAlign(colItem)}"
            >{{ colItem.title }}</th>
          </tr>
        </thead>
      </table>
    </div>

    <div ref="dataTableBox" class="table-body" :style="{height: getHeight()}">

<!--  重点:使用引入的autoScroll组件 -->
<!--  $refs.dataTableBox 为监听的滚动的容器 dataTableBox 为容器 ref属性对应的值 -->
      <auto-scroll ref="autoScroll" :ele="$refs.dataTableBox" :step="0" :interval="1500" :mode="2" />

      <table ref="dataTable" class="layui-table" style="background: #0001271a;">
        <colgroup>
          <col v-for="(colItem, idx3) in cols" :key="'col2-' + idx3" :style="{width: getColWidth(colItem)}"/>
        </colgroup>
        <!-- <tbody ref="dataTableBody" v-if="data && data.length > 0" @mouseover="stopScroll" @mouseleave="startToScroll"> -->
<!-- 重点:鼠标移入或移动时停止滚动,鼠标移除时继续开始滚动 -->
        <tbody ref="dataTableBody" v-if="data && data.length > 0" @mousemove="stopScroll2" @mouseover="stopScroll2" @mouseleave="startToScroll2">

          <tr v-for="(dtItem, idx5) in data" :key="'dt-' + idx5" :class="[idx5%2 == 1 ? 'color1' : '']">
            <td v-for="(colItem, idx6) in cols" :key="'col3-' + idx6" :style="{textAlign: getAlign(colItem)}">
              <div v-if="colItem.type && colItem.type == 'num'">{{ idx5 + 1 }}</div>
              <div v-else>{{ dtItem[colItem.field] }}</div>
            </td>
          </tr>
        </tbody>
        <tbody v-else>
          <tr class="color1">
            <td :colspan="cols.length" style="text-align: center;">暂无数据</td>
          </tr>
        </tbody>
      </table>
    </div>
    <div :class="[isShow==5?'load_more':'load_more1']" v-if="isload">
      <div @click="loadMore()">加载更多<img src="../assets/images/loadMore.png" alt=""></div>
    </div>
  </div>
</template>

<script>
import autoScroll from './autoScroll.vue'

export default {
  name: 'tablePy',
  components: {autoScroll},
  props: {
    "cols": {
      type: Array,
      default: [
        {type: "num", title: '序号'},
        {field: "field1", title: '字段1'},
        {type: "field2", title: '字段2'},
      ]
    }, 
    "data": {
      type: Array,
      default: []
    }, 
    "isload": {
      type: Boolean,
      default: false
    }, 
    "height": {
      type: String|Number,
      default: 190
    }
  },
  data() {
    return {
      datas: [],
      // autoScroll: autoScroll,
      scrollInterval: undefined
    }
  },
  watch: {
    data() {
// 重点:监听到表格数据变化时,等待数据表格渲染完成,再开始渲染自动滚动     
// this.$refs.autoScroll.scrollStep 动态的修改间歇式滚动的步进值
      this.$nextTick(() => {
        // this.ele = this.$refs.dataTableBox;
        this.$refs.autoScroll.scrollStep = this.$refs.dataTableBody.firstElementChild.offsetHeight;
        this.startToScroll2();
      });
    }
  },
  methods: {
    loadMore() {
      this.$emit('loadMore');
      return false;
    },
    getTitle(colItem) {
      const title = colItem.title;
      if (title) {
        return title;
      } else {
        if (colItem.type && colItem.type == 'num') {
          return '序号';
        } else {
          return colItem.field;
        }
      }
    },
    getColWidth(colItem) {
      const type = colItem.type;
      const width = colItem.width;
      if (width) {
        if ((width + '').slice(-1) == '%' || (width + '').slice(-2) == 'px') {
          return width;
        } else {
          return width + 'px';
        }
      } else {
        if (type && 'num' == type) {
          return 80 + 'px';
        } else {
          return 'auto';
        }
      }
    },
    getAlign(colItem) {
      const align = colItem.align;
      if (align && ('center' == align || 'left' == align || 'right' == align)) {
        return align;
      } else {
        return left;
      }
    },
    getHeight() {
      if ((this.height + '').slice(-1) == '%' || (this.height + '').slice(-2) == 'px') {
        return this.height;
      } else {
        if (Number(this.height) < 90) {
          return '90px';
        } else {
          return this.height + 'px';
        }
      }
    },
    stopScroll2() {
    // 修改子组件变量值,调用子组件停止滚动方法
      this.$refs.autoScroll.stopScrollTopFlag = true;
      this.$refs.autoScroll.stopScrollTop();
    },
    startToScroll2() {
// 调用子组件开始滚动方法
      this.$refs.autoScroll.stopScrollTopFlag = false;
      this.$refs.autoScroll.autoScrollTop();
    }
  },
  mounted() {
      // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
      this.$once('hook:beforeDestroy', () => {         
        this.stopScroll2();
      });
  }
};
</script>

<style lang="less" scoped>
.table-body {
  width: 100%;
  overflow-y: auto;
}

.table-body::-webkit-scrollbar {
  width: 0;
}

table.layui-table {
  margin: 0;
  width: 100%;
  color: #ffffff;
  background: rgba(14, 43, 117, 0.3);
  
  thead {
    tr {
      background: rgba(14, 43, 117, 0.3);
    }
  }

  // tr {
  //   width: 100%;
  //   display: flex;
  //   overflow: hidden;
  //   background: rgba(14, 43, 117, 0.5);
  // }

  th, td {
    border: none;
    font-size: 16px;
    padding: 9px 3px;
  }

  .color1 {
    background: #07164e88;
  }

  tbody tr:hover {
    background: rgba(14, 43, 117, 0.6);
  }
}

.load_more {
  margin-top: 0.4rem;
  width: 110%;
  height: 0.45rem;
  border: 0.01rem solid #32c5ff;
  font-size: 0.16rem;
  line-height: 0.45rem;
  text-align: center;
  cursor: pointer;
  margin-bottom: 0.5rem;
  color: #32c5ff;
  img {
    width: 0.2rem;
    height: 0.12rem;
  }
}

.load_more1 {
  margin-top: 0.4rem;
  width: 100%;
  height: 0.45rem;
  border: 0.01rem solid #32c5ff;
  font-size: 0.16rem;
  line-height: 0.45rem;
  text-align: center;
  cursor: pointer;
  margin-bottom: 0.5rem;
  color: #32c5ff;

  img {
    width: 0.2rem;
    height: 0.12rem;
  }
}
</style>
View Code

代码比较多,第二段中相应的引用和使用方法已做 注明。

目前只写了纵向滚动的,等有时间再补充横向滚动的相关效果

posted @ 2022-06-28 20:25  金刀3691  阅读(420)  评论(0编辑  收藏  举报