当前位置:   article > 正文

element-ui-解决下拉框数据量过多问题(vue-virtual-scroll-list)_element-ui下拉框数据太多如何优化

element-ui下拉框数据太多如何优化

参考链接:vue插件 vue-virtual-scroll-list解决数据量太大问题 - 知乎

vue-virtual-scroll-list与selectLoadmore对比:
vue-virtual-scroll-list:一次性返回所有数据。即数据量适中,几千到一两万条,可一次性被后台接口返回的情况下,建议使用vue-virtual-scroll-list。
selectLoadmore:可懒加载下拉框,数据量超级大,几万甚至十几万条以上,后台无法一次性返回,只能分页加载的情况下,建议使用selectLoadmore。
一、第一步:安装

npm install vue-virtual-scroll-list@2.3.4 --save

二、第二步:封装最底层组件

/components/virtualScrollList/select.vue

  1. <template>
  2. <div>
  3. <el-select :placeholder="!disabled?placeholder:'——'" :disabled="disabled" :value="defaultValue" popper-class="virtualselect" filterable :filter-method="filterMethod" @visible-change="visibleChange" v-bind="$attrs" v-on="$listeners">
  4. <virtual-list ref="virtualList" class="virtualselect-list"
  5. :data-key="selectData.value"
  6. :data-sources="selectArr"
  7. :data-component="itemComponent"
  8. :keeps="20"
  9. :extra-props="{
  10. label: selectData.label,
  11. value: selectData.value,
  12. isRight: selectData.isRight
  13. }"></virtual-list>
  14. </el-select>
  15. </div>
  16. </template>
  17. <script>
  18. import virtualList from 'vue-virtual-scroll-list'
  19. import ElOptionNode from './el-option-node'
  20. export default {
  21. components:{
  22. 'virtual-list': virtualList
  23. },
  24. model: {
  25. prop: 'defaultValue',
  26. event: 'change',
  27. },
  28. props: {
  29. disabled: {
  30. type: Boolean,
  31. default: false
  32. },
  33. selectData: {
  34. type: Object,
  35. default () {
  36. return {}
  37. }
  38. },//父组件传的值
  39. defaultValue: {
  40. type: String,
  41. default: ''
  42. },
  43. placeholder: {
  44. type: String,
  45. default: ''
  46. }
  47. },
  48. mounted() {
  49. this.init();
  50. },
  51. watch: {
  52. 'selectData.data'() {
  53. this.init();
  54. }
  55. },
  56. data() {
  57. return {
  58. itemComponent: ElOptionNode,
  59. selectArr:[]
  60. }
  61. },
  62. methods: {
  63. init() {
  64. if(!this.defaultValue) {
  65. this.selectArr = this.selectData.data;
  66. }else {
  67. // 回显问题
  68. // 由于只渲染20条数据,当默认数据处于20条之外,在回显的时候会显示异常
  69. // 解决方法:遍历所有数据,将对应回显的那一条数据放在第一条即可
  70. this.selectArr = JSON.parse(JSON.stringify(this.selectData.data));
  71. let obj = {};
  72. for (let i = 0; i < this.selectArr.length; i++) {
  73. const element = this.selectArr[i];
  74. if(element[this.selectData.value] === this.defaultValue) {
  75. obj = element;
  76. this.selectArr.splice(i,1);
  77. break;
  78. }
  79. }
  80. this.selectArr.unshift(obj);
  81. }
  82. },
  83. // 搜索
  84. filterMethod(query) {
  85. if (query !== '') {
  86. this.$refs.virtualList.scrollToIndex(0);//滚动到顶部
  87. setTimeout(() => {
  88. this.selectArr = this.selectData.data.filter(item => {
  89. return this.selectData.isRight?
  90. (item[this.selectData.label]?.indexOf(query) > -1 || item[this.selectData.value]?.indexOf(query) > -1)
  91. :item[this.selectData.label]?.indexOf(query) > -1;
  92. });
  93. },100)
  94. } else {
  95. this.init();
  96. }
  97. },
  98. visibleChange(bool) {
  99. if(!bool) {
  100. this.$refs.virtualList.reset();
  101. this.init();
  102. }
  103. }
  104. }
  105. }
  106. </script>
  107. <style lang="scss" scoped>
  108. .virtualselect {
  109. // 设置最大高度
  110. &-list {
  111. max-height:245px;
  112. overflow-y:auto;
  113. }
  114. .el-scrollbar .el-scrollbar__bar.is-vertical {
  115. width: 0;
  116. }
  117. }
  118. </style>

/components/virtualScrollList/el-option-node.vue

  1. <template>
  2. <el-option :key="label+value" :label="source[label]" :value="source[value]">
  3. <span>{{source[label]}}</span>
  4. <span v-if="isRight" style="float:right;color:#939393">{{source[value]}}</span>
  5. </el-option>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'item-component',
  10. props: {
  11. index: {
  12. type: Number
  13. },// 每一行的索引
  14. source: {
  15. type: Object,
  16. default () {
  17. return {}
  18. }
  19. },// 每一行的内容
  20. label: {
  21. type: String
  22. },// 需要显示的名称
  23. value: {
  24. type: String
  25. },// 绑定的值
  26. isRight: {
  27. type: Boolean,
  28. default () {
  29. return false
  30. }
  31. }// 右侧是否显示绑定的值
  32. }
  33. }
  34. </script>
三、第三步:封装倒数第二层组件
举例1:classification.vue
  1. <template>
  2. <cw-select :class="classname" :disabled="disabled" :placeholder="placeholder" :selectData="selectData" v-model="value" clearable @change="selectChange"></cw-select>
  3. </template>
  4. <script>
  5. import CwSelect from '@/components/virtualScrollList/select.vue'
  6. export default {
  7. name:'classification',
  8. components: {
  9. CwSelect
  10. },
  11. props:['defaultValue','disabled','classname','placeholder'],
  12. computed: {
  13. dictData() {
  14. return this.$store.state.app.ybDictMap.yb_dept
  15. },
  16. },
  17. data() {
  18. return {
  19. selectData: {
  20. data:[],// 下拉框数据
  21. label: 'name',// 下拉框需要显示的名称
  22. value: 'value',// 下拉框绑定的值
  23. isRight: false,//右侧是否显示
  24. },
  25. value:this.defaultValue,
  26. selectArr:[]
  27. };
  28. },
  29. watch: {
  30. defaultValue(newVal,oldVal) {
  31. this.value = newVal
  32. if(!oldVal&&newVal){
  33. this.huixian()
  34. }
  35. }
  36. },
  37. mounted() {
  38. this.selectData.data = []
  39. this.selectData.data = this.dictData
  40. },
  41. methods: {
  42. selectChange(val) {
  43. this.$emit('change', val)
  44. console.log('下拉框选择的值', val)
  45. },
  46. huixian(){
  47. this.selectArr = JSON.parse(JSON.stringify(this.selectData.data));
  48. let obj = {};
  49. for (let i = 0; i < this.selectArr.length; i++) {
  50. const element = this.selectArr[i];
  51. if(element[this.selectData.value] === this.defaultValue) {
  52. obj = element;
  53. this.selectArr.splice(i,1);
  54. break;
  55. }
  56. }
  57. !!obj && this.selectArr.unshift(obj);
  58. this.selectData.data=[...this.selectArr];
  59. }
  60. }
  61. };
  62. </script>
举例2:staffList.vue
  1. <template>
  2. <cw-select :class="classname" :disabled="disabled" :placeholder="placeholder" :selectData="selectData" v-model="value" clearable @change="selectChange"></cw-select>
  3. </template>
  4. <script>
  5. import CwSelect from '@/components/virtualScrollList/select.vue'
  6. export default {
  7. name:'staffList',
  8. components: {
  9. CwSelect
  10. },
  11. props: {
  12. type: {
  13. type: String,
  14. default:''
  15. },
  16. defaultValue: {
  17. type: String
  18. },
  19. disabled: {
  20. type: Boolean
  21. },
  22. classname: {
  23. type: Object
  24. },
  25. placeholder: {
  26. type: String
  27. },
  28. },
  29. computed: {
  30. staffList() {//科室人员
  31. return this.$store.state.app.busStaffList
  32. },
  33. },
  34. watch: {
  35. defaultValue(newVal,oldVal) {
  36. this.value = newVal
  37. if(!oldVal&&newVal){
  38. this.huixian()
  39. }
  40. }
  41. },
  42. data() {
  43. return {
  44. value:this.defaultValue,
  45. selectData: {
  46. data:[],// 下拉框数据
  47. label: 'name',// 下拉框需要显示的名称
  48. value: 'value',// 下拉框绑定的值
  49. isRight: false,//右侧是否显示
  50. },
  51. selectArr:[]
  52. };
  53. },
  54. mounted() {
  55. if(this.type=='ybList'){
  56. this.selectData.data = JSON.parse(JSON.stringify(this.staffList).replace(/empName|miCode/g, function(matchStr) {
  57. var tokenMap = {
  58. 'empName': 'name',
  59. 'miCode': 'value',
  60. };
  61. return tokenMap[matchStr];
  62. }))
  63. }else{
  64. this.selectData.data = JSON.parse(JSON.stringify(this.staffList).replace(/empName|empId/g, function(matchStr) {
  65. var tokenMap = {
  66. 'empName': 'name',
  67. 'empId': 'value',
  68. };
  69. return tokenMap[matchStr];
  70. }))
  71. }
  72. },
  73. methods: {
  74. selectChange(val) {
  75. let item=this.selectData.data.find((i)=>{
  76. return i.value===val
  77. })
  78. this.$emit('change', {value:val,name:item?.name})
  79. console.log('下拉框选择的值', {value:val,name:item?.name})
  80. },
  81. huixian(){
  82. this.selectArr = JSON.parse(JSON.stringify(this.selectData.data));
  83. let obj = {};
  84. for (let i = 0; i < this.selectArr.length; i++) {
  85. const element = this.selectArr[i];
  86. if(element[this.selectData.value] === this.defaultValue) {
  87. obj = element;
  88. this.selectArr.splice(i,1);
  89. break;
  90. }
  91. }
  92. !!obj && this.selectArr.unshift(obj);
  93. this.selectData.data=[...this.selectArr];
  94. }
  95. }
  96. };
  97. </script>
第四步:使用
  1. <classification placeholder="请选择" :disabled="disabled" :defaultValue="base.miDscgCaty" type="miDscgCaty" @change="(val) => changeClass(val, 'miDscgCaty')" :classname="{'warnQc':warnField?.miDscgCaty,'errorQc':errorField?.miDscgCaty}"/>
  2. <staffList type="ybList" placeholder="请选择" :disabled="disabled" :defaultValue="base.chfpdrName" @change="(val) => changeStaff(val,'chfpdrName','chfpdrCode')" :classname="{'warnQc':warnField?.chfpdrName,'errorQc':errorField?.chfpdrName}"/>

 待补充:多选等功能 封装el-select,实现虚拟滚动,可单选、多选、搜索查询、创建条目-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/114805
推荐阅读
相关标签
  

闽ICP备14008679号