下拉框渲染大量数据时的解决方案

Posted 六月June June

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了下拉框渲染大量数据时的解决方案相关的知识,希望对你有一定的参考价值。

如果在下拉框中直接一次性渲染几百上千条数据可能导致页面卡死或报错,所以要分批次载入。使用频率较高,所以封装成一个组件,该组件效果类似于触底加载。支持搜索,且能够正常回显数据。该组件可拿来即用

组件代码

// 下拉框渲染多数据时的解决方案
<template>
  <a-form-model-item :label="config.label" :prop="config.prop" :rules="rules">
    <a-select
      allowClear
      show-search
      style="width: 100%"
      v-model="form[config.prop]"
      option-filter-prop="children"
      :placeholder="loading ? '正在加载...' : '请选择'"
      :mode="mode"
      :loading="loading"
      :disabled="loading"
      @popupScroll="handlePopupScroll"
      @search="handleSearch"
      @select="handleSelect"
    >
      <a-select-option v-for="(item, index) in options" :key="index" :value="item[config.code]">
         item[config.name] 
      </a-select-option>
    </a-select>
  </a-form-model-item>
</template>

<script>
import debounce from 'lodash/debounce'

export default 
  props: 
    // 一个引用类型数据,达到双向绑定的作用
    form:  type: Object, default: () =>  ,
    rules:  type: Array, default: () => [] ,// 表单验证
    originData:  type: Array, default: () => [] ,// 原始数据
    mode:  type: String, default: 'default' ,// 多选还是单选 multiple为多选
    // 配置项 label:'船舶名称',prop:'vesselName',code:'vesselId',name:'vesselName'
    // code为下拉数据显示的值,name为下拉数据提交的值
    config:  type: Object, default: () =>  ,
  ,
  data () 
    // this.searchUser = debounce(this.searchUser, 800) // 防抖
    return 
      searchName: null, // 下拉框搜索值
      loading: false, // 下拉框数据加载
      options: [], // 下拉框中载入数据
    
  ,
  watch: 
    originData: function (newVal, oldVal) 
      if (newVal && newVal.length > 0) 
        this.getOptions(newVal)
      
    ,
  ,
  methods: 
    // 得到下拉框中的载入数据
    getOptions () 
      if (this.searchName) 
        // 根据搜索值过滤数据
        const data = this.originData.filter(
          (x) => x[this.config.name] && x[this.config.name].indexOf(this.searchName) > -1
        )
        this.options = data
       else 
        // 展示前20条数据
        this.options = this.originData < 20 ? this.originData : this.originData.slice(0, 20)
        // 用于回显 这样写就需要,先查询表单数据再查询下拉数据
        if (this.form[this.config.prop]) 
          // select的mode是否为多选
          let data = []
          if (this.mode === 'multiple') 
            data = this.originData.filter((x) => this.form[this.config.prop].includes(x[this.config.code]))
           else 
            data = this.originData.filter((x) => this.form[this.config.prop] === x[this.config.code])
          
          if (data && data.length > 0) 
            this.options = [...this.options, ...data]
          
        
      
    ,
    // 下拉列表滚动事件
    // 实现思路:当前下拉的展示列表+10小于全部数据的长度,newArr为新加载的10条数据,当前展示列表拼上新加载的10条;否则, newArr为全部列表中剩余的数据,当前展示列表拼上剩余的数据。
    handlePopupScroll: debounce(function () 
      if (this.loading === false) 
        const curLen = this.options.length
        const allLen = this.originData.length
        if (curLen + 10 < allLen) 
          const newArr = this.originData.slice(curLen, curLen + 10)
          this.options = this.options.concat(newArr)
         else 
          const newArr = this.originData.slice(curLen, allLen)
          this.options = this.options.concat(newArr)
        
      
    , 500),
    // 搜索事件
    handleSearch: debounce(function (val) 
      this.searchName = val
      this.getOptions()
    , 500),
    // 选中事件
    handleSelect () 
      if (this.searchName) 
        this.searchName = null
        this.getOptions()
      
    ,
  ,

</script>

使用组件

<template>
    <a-form-model :model="form" :rules="rules">
        <!-- 多选时需要添加mode="multiple",并且form里的member属性值要改为数组 -->
        <SelectLimit
        :form="form"
        :rules="rules.member"
        :originData="originData"
        :config=" label: '船舶名称', prop: 'member', code: 'id', name: 'name' "
        />
    </a-form-model>
</template>

<script>
import SelectLimit from '@/components/MyComponents/SelectLimit/index.vue' // 渲染多数据的下拉框
import  query  from '@/views/yangtze/express/vessel/service/vesselService' // 根据实际修改

export default 
  name: 'BaseForm',
  components:  SelectLimit ,
  data () 
    return 
      form: 
        // member: ['11240002','11240019'] ,// mode: 'multiple'
        member: '11240002'
      ,
      rules: 
        member: [ required: true, message: '必填' ],
      ,
      originData: [], // 原始数据
    
  ,
  mounted () 
    this.queryOriginData() // 查询全部数据
  ,
  methods: 
    // 查询全部数据
    queryOriginData () 
      const param =  current: 1, pageSize: 100 
      query(param).then((res) => 
        if (res.code === '0') 
          const data = res.data || 
          const list = data.list || []
          this.originData = list.map((x) => ( id: x.id, name: x.name )) // 得到全部数据
        
      )
    ,
  ,

</script>

以上是关于下拉框渲染大量数据时的解决方案的主要内容,如果未能解决你的问题,请参考以下文章

下拉框渲染大量数据时的解决方案

Vue:解决 element-ui 下拉框过多导致卡顿问题

vue基于element实现根据下拉框选择渲染不同的数据

vue基于element实现根据下拉框选择渲染不同的数据

layui下拉框渲染问题,以及回显问题

php简易表单及下拉框动态渲染