Native table implements polling + css to modify the default scroll bar style

There are two requirements in the recent project (vue Series). Here is a record to share with you.

Polling by native Table list

Demand:
  1. Do not poll when the number of table lists is small, and only poll when the number exceeds a certain height;
  2. Move the mouse in to pause polling, move out to continue polling

First, the prototype is as follows:

There is a paging in the lower right corner. It uses the paging component of the elementUI. After changing the style, the main body is a native table
There are several ways to implement polling. There are many ways to search and search on the Internet. I use js here. The general idea is to control margin top, such as margin top = - 1px, margin top = - 2px; margin top = - 3px;. When the value is greater than the row height, it means that the data has been scrolled. At this time, recover margin top = 0 and insert it into the bottom of tbody to implement polling . Direct code:

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">Equipment type</th>
              <th class="name">Major categories of equipment</th>
              <th class="code">Equipment number</th>
              <th class="pos">Device location</th>
              <th class>Task delay</th>
              <th class="sysState">Device status</th>
              <th class="pro">Task completion progress</th>
              <th class="pro">Task start time</th>
              <th class="pro">Task end time</th>
              <th class="pro">Task duration</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 !== 'Concrete ceiling grinding') || 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; /* nowrap */
  white-space: nowrap; /* nowrap */
  overflow: hidden; /* Hide excess content when content exceeds width */
  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 polling method:

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)
          }
        })
      }
    }
  }

At this point, the table polling function has been implemented.
After a period of time, the boss said that he didn't need to poll first and replaced it with a scroll bar.

css modifying the default scroll bar style

On the original basis, it can be implemented with only a little change. Here is the implementation of css:

css

.scroll-box {
  width: 100%;
  height: 510px;
  overflow: hidden;
  overflow-y: scroll;
  position: relative;
  // Change the default scroll bar style
  // Change the default scroll bar style
  &::-webkit-scrollbar {/*Scroll bar overall style*/
    width: 6px;         /*Height and width correspond to the size of horizontal and vertical scroll bars respectively*/
    height: 6px;
    background: transparent;
  }

  &::-webkit-scrollbar-thumb {/*Small square in scroll bar*/
    background: transparent;
    border-radius: 4px;
  }

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

  &:hover::-webkit-scrollbar-track {/*Inner track of scroll bar*/
    background: hsla(0, 0%, 53%, 0.1);
  }
  // If you need to poll the table, please comment out the above and release the following
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

OK, that's OK. It will appear when the mouse is moved in. The following is the effect:

Keywords: Front-end network Vue IE

Added by wizhippo on Thu, 21 Nov 2019 19:58:29 +0200