1
头图
If you think I'm doing a good job, please give me a thumbs up, thank you. Whee

Scenes

Concubine of Kangxi

image.png

image.png

It is said that this year is the 53rd year of Kangxi, and the world is at peace. No one in the world does not sigh this "Kangxi prosperous age", Kangxi himself is very happy, "I have struggled for most of my life, but I still can't enjoy myself, so I passed on Zhang Tingyu. See me, I have something for him to do!"
  • Kangxi: Hengchen (Hengchen is Zhang Tingyu's word), how is this Kangxi prosperous
  • Zhang Tingyu: The emperor is awesome, the emperor is awesome, long live the emperor
  • Kangxi: But I'm getting old, but I can't obey the old, I want to prove it to the world
  • Zhang Tingyu: The emperor is in his prime, long live, long live
  • Kangxi: I don't care, I want to choose a concubine, I want to choose a concubine, I want to choose a concubine! ! !
  • Zhang Tingyu: I tm. . . Your tm is 60, still choose? Can you handle it? big brother!
  • Kangxi: I don't care, you find it for me, find 10,000 young women to enter the palace, I want to choose a concubine
  • Zhang Tingyu: Choose a hair, you can't stand it - Kangxi: I don't care, I have deer blood, a cup of deer blood, and my mana is boundless
  • Zhang Tingyu: No, you can't.
  • Kangxi: Are you going?
  • Zhang Tingyu: no
  • Kangxi: Are you going?
  • Zhang Tingyu: I'm not going
  • Kangxi: Do you still want to enjoy the Taimiao?
  • Zhang Tingyu: Long live the emperor, the minister must go to the sacred trust

    A month later, 10,000 young women entered the palace. But the problem came again. There are so many women, it is impossible for Kangxi to choose it at one time, it must not cost his eyes.
Ting - yu had an idea: let woman who fed- hall to let the emperor election thing. Specifically, you can do this:
  • main hall of 161df80a235251 where the emperor chose his concubine, two more side halls.
  • The maids entered the hall in batches for the emperor to see
  • The maids who have been seen enter the left side hall to wait for the result of the selection of the concubine, and the maids who have not been lined up wait in the right side hall

    This not only improves the efficiency of the draft, but also makes it easier for the emperor. The benefits of doing this are:
  • The emperor does not need to see 10,000 palace maids at a time, and he does not need to be so tired
  • If the emperor is half-tired, he can rest and choose again the next day. Anyway, the number of batches selected has been recorded.
  • If the emperor recalls which palace maid is not bad one day, he can also check back.

Multiple data rendering

Now to solve multi-data rendering, I believe you may think of paging, bottom loading, lazy loading, etc., but in fact, virtual list is also an important solution for multi-data high-performance loading.

The concept of virtual lists

Virtual scrolling is based on the volume of the list in the visible area container, listening for user sliding or scrolling events, dynamically intercepting the part of the long list data and rendering it to the page, and dynamically filling the container up and down scrolling area with blank stations Content, simulating native scrolling effect
image.png
  • Browser rendering === Kangxi draft: Rendering 10,000 at a time will definitely put a lot of pressure on the browser and cause poor user experience
  • Container visible area === Draft hall: 10,000 are queued for rendering, such as 10 at a time
  • The upper and lower areas === left and right side halls: it's not your turn to render, you just go into the blank area and wait

accomplish

Basic implementation

  • height of viewable area
  • the height of the list item
  • The number of list items that can be displayed in the visible area = ~~(viewable area height / list item height) + 2
  • start index
  • end index
  • Preloading (to prevent scrolling too fast, causing a temporary white screen)
  • According to the start index and end index, the intercepted data is displayed in the visible area
  • rolling throttle
  • The upper and lower blank areas are implemented using padding
  • Swipe to the end, request data again and splicing
<template>
  <div class="v-scroll" @scroll.passive="doScroll" ref="scrollBox">
    <div :style="blankStyle" style="height: 100%">
      <div v-for="item in tempSanxins" :key="item.id" class="scroll-item">
        <span>{{ item.msg }}</span>
        <img :src="item.src" />
      </div>
    </div>
  </div>
</template>


<script>
import { throttle } from "../../utils/tools";
export default {
  data() {
    return {
      allSanxins: [], // 所有数据
      itemHiehgt: 150, // 列表每一项的宽度
      boxHeight: 0, // 可视区域的高度
      startIndex: 0, // 元素开始索引
    };
  },
  created() {
    // 模拟请求数据
    this.getAllSanxin(30);
  },
  mounted() {
    // 在mounted时获取可视区域的高度
    this.getScrollBoxHeight();
    // 监听屏幕变化以及旋转,都要重新获取可视区域的高度
    window.onresize = this.getScrollBoxHeight;
    window.onorientationchange = this.getScrollBoxHeight;
  },
  methods: {
    getAllSanxin(count) {
      // 模拟获取数据
      const length = this.allSanxins.length;
      for (let i = 0; i < count; i++) {
        this.allSanxins.push({
          id: `sanxin${length + i}`,
          msg: `我是三心${length + i}号`,
          // 这里随便选一张图片就行
          src: require("../../src/asset/images/sanxin.jpg").default,
        });
      }
    },
    // 使用节流,提高性能
    doScroll: throttle(function () {
      // 监听可视区域的滚动事件
      // 公式:~~(滚动的距离 / 列表项 ),就能算出已经滚过了多少个列表项,也就能知道现在的startIndex是多少
      // 例如我滚动条滚过了160px,那么index就是1,因为此时第一个列表项已经被滚上去了,可视区域里的第一项的索引是1
      const index = ~~(this.$refs.scrollBox.scrollTop / this.itemHiehgt);
      if (index === this.startIndex) return;
      this.startIndex = index;
      if (this.startIndex + this.itemNum > this.allSanxins.length - 1) {
        this.getAllSanxin(30);
      }
    }, 200),
    getScrollBoxHeight() {
      // 获取可视区域的高度
      this.boxHeight = this.$refs.scrollBox.clientHeight;
    },
  },
  computed: {
    itemNum() {
      // 可视区域可展示多少个列表项? 计算公式:~~(可视化区域高度 / 列表项高度) + 2
      // ~~是向下取整的运算符,等同于Math.floor(),为什么要 +2 ,是因为可能最上面和最下面的元素都只展示一部分
      return ~~(this.boxHeight / this.itemHiehgt) + 2;
    },
    endIndex() {
      // endIndex的计算公式:(开始索引 + 可视区域可展示多少个列表项 * 2)
      // 比如可视区域可展示8个列表项,startIndex是0的话endIndex就是0 + 8 * 2 = 16,startIndex是1的话endIndex就是1 + 8 * 2 = 17,以此类推
      // 为什么要乘2呢,因为这样的话可以预加载出一页的数据,防止滚动过快,出现暂时白屏现象
      let index = this.startIndex + this.itemNum * 2;
      if (!this.allSanxins[index]) {
         // 到底的情况,比如startIndex是99995,那么endIndex本应该是99995 + 8 * 2 = 10011
        // 但是列表数据总数只有10000条,此时就需要让endIndex = (列表数据长度 - 1)
        index = this.allSanxins.length - 1;
      }
      return index;
    },
    tempSanxins() {
      //   可视区域展示的截取数据,使用了数组的slice方法,不改变原数组又能截取
      let startIndex = 0;
      if (this.startIndex <= this.itemNum) {
        startIndex = 0;
      } else {
        startIndex = this.startIndex + this.itemNum;
      }
      return this.allSanxins.slice(startIndex, this.endIndex + 1);
    },
    blankStyle() {
      // 上下方的空白处使用padding来充当
      let startIndex = 0;
      if (this.startIndex <= this.itemNum) {
        startIndex = 0;
      } else {
        startIndex = this.startIndex - this.itemNum;
      }
      return {
        // 上方空白的高度计算公式:(开始index * 列表项高度)
        // 比如你滚过了3个列表项,那么上方空白区高度就是3 * 150 = 450,这样才能假装10000个数据的滚动状态
        paddingTop: startIndex * this.itemHiehgt + "px",
         // 下方空白的高度计算公式:(总数据的个数 - 结束index - 1) * 列表项高度
        // 例如现在结束index是100,那么下方空白高度就是:(10000 - 100 - 1) * 150 = 1,484,850
        paddingBottom:
          (this.allSanxins.length - this.endIndex - 1) * this.itemHiehgt + "px",
          // 不要忘了加px哦
      };
    },
  },
};
</script>

<style lang="scss" scoped>
.v-scroll {
  height: 100%;
  /* padding-bottom: 500px; */
  overflow: auto;

  .scroll-item {
    height: 148px;
    /* width: 100%; */
    border: 1px solid black;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 20px;

    img {
      height: 100%;
    }
  }
}
</style>

Conclusion!

I'm Lin Sanxin, an enthusiastic front-end rookie programmer. If you are motivated, like the front-end, and want to learn the front-end, then we can make friends and fish together haha, touch the fish group, add me, please note [Si No]

image.png


Sunshine_Lin
2.1k 声望7.1k 粉丝