1

最近做项目(vue系列)遇到两个需求,这里做一个记录,分享给大家。

原生Table列表实现轮询

需求:
  1. 当table列表数量较少时不轮询,超过一定高度才轮询;
  2. 鼠标移入暂停轮询,移出继续轮询

首先,原型图长下面这样:
原型图
右下角有个分页,用的是elementUI的分页组件,改了下样式,主体就是一个原生table
轮询有好几种实现方式,网上搜一搜很多,我这里使用js的方式实现,大概的思路就是:通过控制margin-top,比如margin-top=-1px,margin-top=-2px;margin-top=-3px;...,当这个值大于行高时,说明这条数据已经滚动完毕了,这时恢复margin-top=0,并且将它插入到tbody底部,从而实现轮询。直接上代码:

HTML
 <div class="network-container">
    <div class="network-center">
      <img src="./imgs/img_map_bg_02.png" />
      <img src="./imgs/img_map_bg_04.png" />
      <div class="network-center-content">
        <table class="deviceInfoBox">
          <thead>
            <tr>
              <th class="name">设备类型</th>
              <th class="name">设备大类</th>
              <th class="code">设备编号</th>
              <th class="pos">设备位置</th>
              <th class>任务延时</th>
              <th class="sysState">设备状态</th>
              <th class="pro">任务完成进度</th>
              <th class="pro">任务开始时间</th>
              <th class="pro">任务结束时间</th>
              <th class="pro">任务时长</th>
            </tr>
          </thead>
        </table>
        <div class="scroll-box" ref="scrollBox">
          <table
            class="tab-scroll"
            ref="scroll"
            @mouseenter="activeEve(false)"
            @mouseleave="activeEve(true)"
          >
            <tbody>
              <tr v-for="(si,idx) in deviceInfoList" :key="idx">
                <td class="name">{{si.name || '-'}}</td>
                <td class="type">{{si.type || '-'}}</td>
                <td class="code">
                  <a
                    @click="handleClick(si)"
                    :class="{'isDisabled':(si.name !== '混凝土天花打磨') || si.sysState !== '3'}"
                  >{{si.deviceCode || '-'}}</a>
                </td>
                <td class="pos">{{si.posistion || '-'}}</td>
                <td class="pos" v-if="si.sysState == '3'">{{Number(si.delayedTime)+'ms'}}</td>
                <td class="pos" v-else>{{si.delayedTime || '-'}}</td>
                <td
                  class="sysState"
                  :class="{'yellow': si.sysState == '2', 'green': si.sysState == '3'}"
                >{{deviceStateArr[si.sysState] || '-'}}</td>
                <td v-if="si.sysState == '3'">
                  <el-progress :percentage="si.progress || 0"></el-progress>
                </td>
                <td v-else>{{si.progress || '-'}}</td>
                <td>{{si.workStartTime || '-'}}</td>
                <td>{{si.workEndTime || '-'}}</td>
                <td>{{si.duration}}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="page-bar">
        <el-pagination
          background
          layout="prev,pager, next"
          :current-page="page"
          :page-size="pageSize"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        ></el-pagination>
      </div>
    </div>
  </div>
</template>
CSS
<style scoped lang='scss'>
table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}
th,
td {
  line-height: 35px;
  color: #ffffff;
  text-align: center;
  word-break: keep-all; /* 不换行 */
  white-space: nowrap; /* 不换行 */
  overflow: hidden; /* 内容超出宽度时隐藏超出部分的内容 */
  text-overflow: ellipsis; /* for IE */
}
.scroll-box {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}
.tab-scroll {
  table-layout: fixed;
  font-size: 16px;
  position: absolute;
  left: 0;
  top: 0;
  border-top: none;
  padding-left: 60px;
  .isDisabled {
    pointer-events: none;
    cursor: not-allowed;
  }
  .yellow {
    color: #dada09;
  }
  .green {
    color: #04ba19;
  }
}
.left-button {
  position: absolute;
  left: 4px;
  padding: 24px 14px;
  top: 50%;
  transform: translate(0, -50%);
  width: 46px;
  height: 221px;
  color: #fff;
  text-align: center;
  line-height: 26px;
  font-size: 18px;
  z-index: 100;
  border: solid 1px #31467d;
  border-left: none;
  color: #65c6e7;
}
.show {
  background: url('../../../assets/dashboard/icon_packup.png');
  width: 12px;
  height: 14px;
  transform: rotate(180deg);
  display: inline-block;
  background-size: contain;
}

.hide {
  background: url('../../../assets/dashboard/icon_packup.png');
  width: 12px;
  height: 14px;
  display: inline-block;
  background-size: contain;
}

.deviceInfoBox {
  table-layout: fixed;
  font-size: 16px;
  color: #fff;
  width: 100%;
  z-index: 50;
  text-align: center;
  transition: 500ms all ease-in;
  th {
    color: #65c6e7;
    white-space: nowrap;
  }
  td {
    color: #ffffff;
    white-space: nowrap;
  }
  .yellow {
    color: #dada09;
  }
  .green {
    color: #04ba19;
  }
}
.flex-row-center {
  display: flex;
  flex-direction: row;
  align-items: center;
}
.flex-row {
  display: flex;
  flex-direction: row;
}
.flex-col-center {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.network-container {
  height: 100%;
  overflow: auto;
  min-width: 38.4rem;
  background: url('./imgs/img_bg.png') no-repeat;
  background-size: 100% 100%;
  font-size: 50px;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  > div {
    width: 100%;
  }

  .network-center {
    position: relative;
    margin: 0.2rem 0.4rem 0 0.4rem;
    width: calc(100% - 0.8rem);
    min-height: 9.64rem;
    flex: 1;
    overflow: hidden;
    &:before {
      content: '';
      display: block;
      height: 0.5rem;
      width: 0.5rem;
      position: absolute;
      background: url('./imgs/img_map_bg_01.png') no-repeat;
      background-size: 100% 100%;
      left: 3px;
      top: 3px;
      z-index: 99;
    }
    img {
      position: absolute;
      background-size: 100% 100%;
      height: 0.5rem;
      width: 0.5rem;
      z-index: 99;
    }
    > img:nth-child(1) {
      right: 3px;
      top: 3px;
    }
    > img:nth-child(2) {
      right: 3px;
      bottom: 2px;
    }
    &:after {
      content: '';
      height: 0.5rem;
      width: 0.5rem;
      position: absolute;
      background: url('./imgs/img_map_bg_03.png') no-repeat;
      background-size: 100% 100%;
      bottom: 2px;
      left: 3px;
      z-index: 99;
    }
    .network-center-content {
      border: solid 0.02rem #31467d;
      width: calc(100% - 0.12rem);
      height: 100%;
      margin: 0.06rem;
      overflow: hidden;
      padding-left: 60px;
    }
    .page-bar {
      position: absolute;
      right: 0;
      bottom: 0;
      margin-right: 10px;
      margin-bottom: 10px;
      /deep/.el-pagination.is-background .btn-prev,
      /deep/.el-pagination.is-background .btn-next,
      /deep/.el-pagination.is-background .el-pager li {
        background-color: #04162a;
        border: solid 1px #31467d;
        color: #2bfaff;
        margin: 0 3px;
      }
      /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
        background-color: #43d5d7;
      }
    }
  }
}
</style>

JS

table轮询的方法:

methods: {
    activeEve(val) {
      this.scroll = val 
      const self = this,
        wrapH = this.$refs.scrollBox.clientHeight,
        sel = this.$refs.scroll,
        tbody = sel.children[0],
        tbodyH = tbody.clientHeight
      let timer_s = null,
        step = 0

      if (this.scroll && tbodyH > wrapH) {
        if (self.timer) clearTimeout(self.timer)
        cycle()
      } else {
        if (self.timer) clearTimeout(self.timer)
      }

      function cycle() {
        if (self.timer) clearTimeout(self.timer)
        self.timer = setTimeout(function() {
          scroll()
        }, 2000)
      }

      function scroll() {
        cancelAnimationFrame(timer_s)
        timer_s = requestAnimationFrame(function fn() {
          if (!tbody.children || !tbody.children.length) return
          const trH = tbody.children[0].clientHeight
          if (Math.abs(step) > trH) {
            cancelAnimationFrame(timer_s)
            step = 0
            sel.style.marginTop = 0
            tbody.appendChild(tbody.firstChild)
            cycle()
          } else {
            step--
            sel.style.marginTop = `${step}px`
            timer_s = requestAnimationFrame(fn)
          }
        })
      }
    }
  }

至此,table轮询功能已经实现。
过了一段时间,老大又说先不用轮询,用滚动条代替。

css修改默认滚动条样式

在原来的基础上,只需要一点小改动就可以实现,下面是css实现:

css

.scroll-box {
  width: 100%;
  height: 510px;
  overflow: hidden;
  overflow-y: scroll;
  position: relative;
  // 修改默认滚动条样式
  // 修改默认滚动条样式
  &::-webkit-scrollbar {/*滚动条整体样式*/
    width: 6px;         /*高宽分别对应横竖滚动条的尺寸*/
    height: 6px;
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
    background: transparent;
    border-radius: 4px;
  }

  &:hover::-webkit-scrollbar-thumb {
    background: hsla(0, 0%, 53%, 0.4);
  }

  &:hover::-webkit-scrollbar-track {/*滚动条里面轨道*/
    background: hsla(0, 0%, 53%, 0.1);
  }
  // 如果需要轮询table,请注释掉上面的,放开下面的
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

好了,这样就可以了,鼠标移入的时候会出现,下面是效果:
滚动条.png


少侠
66 声望5 粉丝

这个人不懒,但不知道写啥