【面试】后端一次给你30万option待选项,页面无响应了你怎么办?

本文介绍了一种解决Vue中select组件在处理大量数据时导致浏览器卡死的问题。作者首先尝试了基于elementUI的select组件进行节流优化,只在搜索时加载数据。然后进一步开发了一个虚拟滚动的select组件,利用vue-virtual-scroller插件实现DOM复用,提高性能和用户体验。此外,还封装了一个名为VirtualSelector的自定义插件,提供更高的定制性和灵活性。
摘要由CSDN通过智能技术生成

最近遇到一个问题,在开发编辑页面时候,遇到select大数据量,一个下拉选择器有两万个备选,页面上会不定出现3-18个select,预计可能会渲染30万多个option备选,这么多dom加载,直接把浏览器干无响应了。

第一个构想就是虚拟select

搜索一番没有合适的轮子,vxe-table 比较合适,但是为了一个问题单独引入,不合适,
只能先基于elementUIselect选择器再度封装解决问题,节流版select

第一版,节流select

此版本的select规避页面一打开,就加载所有option导致页面卡死,无法使用为目标

<throttling-select v-model="value" :list="options" :placeholder="placeholder" selkey="key" sellabel="label"></throttling-select>

在vue组件挂载的时候,判断当前selectoption数量是否超过1000个,小于则直接渲染,大于则不渲染只启用搜索渲染,借助于el-select的远程搜索功能实现


<template>
  <el-select
    @visible-change="popChange"
    v-model="selectValue"
    filterable
    remote
    :placeholder="placeholder"
    :remote-method="remoteMethod"
    :loading="loading"
    style="width: calc(98% - 20px)"
  >
    <el-option
      v-for="item in options"
      :key="item[selkey]"
      :label="item[sellabel]"
      :value="item[selkey]"
    >
    </el-option>
  </el-select>
</template>

<script>
export default {
   
  mixins: [],
  filters: {
   },
  components: {
   },
  model: {
   
    prop: 'value', //绑定的值,通过父组件传递
    event: 'update' //自定义名
  },
  props: {
   
    value: {
   
      type: [String, Number],
      default: ''
    },
    list: {
   //选项值
      type: Array,
      default: () => []
    },
    placeholder: {
   
      type: [String, Number],
      default: '选项多,加载慢,建议搜索'
    },
    selkey: {
   
      type: [String, Number],
      default: 'key'
    },
    sellabel: {
   
      type: [String, Number],
      default: 'label'
    }
  },
  data() {
   
    return {
   
      options: [],
      selectValue: '',
      loading: false
    }
  },
  computed: {
   },
  watch: {
   
    selectValue(val) {
   
      console.log(val)
      this.$emit('update', val)
    }
  },
  created() {
   
    this.selectValue = this.value
  },
  mounted() {
   
  },
  destroyed() {
   
  },
  methods: {
   
    popChange(e) {
   
      console.log(e)
      if (e) {
   
        this.loading = true
        this.options = this.list.length > 1000 ? [] : [...this.list]   
        this.loading = false
      }
    },
    remoteMethod(query) {
   
      console.log(query)
      if (query !== '') {
   
        this.loading = true
        this.options = []
        const reg = new RegExp(query.toLowerCase())
        setTimeout(() => {
   
          this.options = this.list.filter(item => {
   
            return reg.test(item[this.selkey].toLowerCase())
          })
          this.loading = false
        }, 50)
      } else {
   
        this.options = []
      }
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped></style>

第二版:虚拟select滚动

基于vue-virtual-scroller插件二次开发,好处是支持大数据,复用dom元素,拖动流畅

虽然作者 已经封装过virtual-selector插件,但是根本还是在virtual-scroller上做的二次封装,只完成了最基本的select功能,定制化不高.

索性自己重新封装,满足自由度。样式嫌丑或者功能不满足请自己改virtualSelector.vue文件

安装npm install -save vue-virtual-scroller

创建virtualSelector.vue文件

//virtualSelector.vue
//开发插件
<template>
  <div
    class="virtual-selector"
    :id="vsId"
  >
    <span
      class="virtual-selector__label"
      :class="{none: !label}"
    >{
   {
    label }}</span>
    <div class="virtual-selector__input-wrapper">
      <input
        class="virtual-selector__input"
        :placeholder="placeholder"
        v-model="selected[option.itemNameKey]"
        @keyup="handleKeyup"
        @input="handleInput"
        @focus="handleFocus($event)"
        @select="handleInputSelect($event)"
      /
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值