# 渲染 10w 条数据

# 题目

后端返回 10w 条数据,该如何渲染?

# 设计是否合理?

前端很少会有一次性渲染 10w 条数据的需求,而且如果直接渲染会非常卡顿。
你可以反问面试官:这是什么应用场景。然后判断这个技术方案是否合理。

例如,就一个普通的新闻列表,后端一次性给出 10w 条数据是明显设计不合理的。应该分页给出。
你能正常的反问、沟通、给出自己合理的建议,这本身就是加分项。

当然,面试官话语权更大,他可能说:对,不合理,但就非得这样,该怎么办?

# 自定义中间层

# 虚拟列表

基本原理

  • 只渲染可视区域 DOM
  • 其他隐藏区域不渲染,只用一个 <div> 撑开高度
  • 监听容器滚动,随时创建和销毁 DOM

虚拟列表实现比较复杂,特别是在结合异步 ajax 加载。明白实现原理,实际项目可用第三方 lib

# 答案

  • 沟通需求和场景,给出自己合理的设计建议
  • 虚拟列表

# 扩展

有时候面试官会出这种刁钻的问题来故意“难为”候选人,把自己扮演成后端角色,看候选人是否好欺负。
如果此时你顺从面试官的问题继续埋头苦思,那就错了。应该适当的追问、沟通、提出问题、给出建议,这是面试官想要看到的效果。

实际工作中,前端和后端、服务端的人合作,那面会遇到各种设计沟通的问题。看你是否有这种实际工作经验。

# vue-virtual-scroll-list 的使用

<template>
  <div>
    <virtual-list
      style="height: 360px; overflow-y: auto"
      scrollable
      :data-key="'ip'"
      :data-sources="items"
      :data-component="itemComponent"
    />
  </div>
</template>

<script>
import Item from './Item'
import VirtualList from 'vue-virtual-scroll-list'
import { getUsers } from '../api/index'
export default {
  name: 'HelloWorld',
  components: { 'virtual-list': VirtualList },
  props: {
    msg: String,
  },
  data() {
    return {
      itemComponent: Item,
      items: [],
    }
  },
  mounted() {
    this.mock()
  },
  methods: {
    async mock() {
      const data = await getUsers()
      this.items = data.userInfo

      console.log(this.items)
    },
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Item.vue

<template>
  <div>{{ index }} - {{ source.username }}</div>
</template>

<script>
export default {
  name: 'item-component',
  props: {
    index: {
      // index of current item
      type: Number,
    },
    source: {
      // here is: {uid: 'unique_1', text: 'abc'}
      type: Object,
      default() {
        return {}
      },
    },
  },
}
</script>

# 效果