最近在做后台管理系统时,需要渲染品牌的数据,但是品牌的数据有2000+数据,导致页面在选择时,页面卡顿到不能使用……

element 必填 element select_数据


上面效果图是v-for遍历的数据,此处只针对单项进行处理,多项的只是加了一个对象的遍历:

首先想到的解决办法是:可搜索

element 必填 element select_下拉列表_02


写法如下:

<el-select v-model="brandId" filterable placeholder="请选择品牌" size="mini" clearable :filter-method="filterMethod" :loading="pploading">
    <el-option v-for="item in ppoptions"
               :key="item.id"
               :label="item.name"
               :value="item.id">
    </el-option>
</el-select>

搜索方法函数如下:

filterMethod(query){//query就是输入的内容,根据输入的内容进行filter数据筛选,然后返回数据
	if(query){
		//如果有输入需要检索的内容,则需要进行筛选,将符合筛选条件的数据赋值给ppotions
		//下面的this.brandData就是2000+的品牌数据
		this.ppotions = this.brandData.filter(item=>{
			//下面的代码是将内容小写后进行匹配,如果indexOf的值>-1,则代表匹配上了
			return item.label.toLowerCase().indexOf(query.toLowerCase())>-1
		})
	}else{
		//如果没有输入内容,则下拉框中的内容为空,下拉框中的内容就是ppotions的数据
		this.ppoptions = [];
	}
}

经过实现,发现这个在数据量很大,也就是this.brandData数据量大的时候,页面还是会卡顿。因为刚开始渲染select组件的时候,还是要将全部的数据渲染出来,然后再根据输入的内容进行筛选,更改下拉列表中的内容。

于是考虑到远程搜索的功能:

element 必填 element select_element 必填_03


这个远程搜索的功能,具体表现就是:刚开始渲染select组件时,并不渲染下拉列表,而是再输入内容后,再根据输入的内容进行筛选,将筛选后的内容渲染到下拉列表中,因此组件下拉列表渲染的内容数据量会少很多。从而解决数据量大卡顿的问题。

代码如下:

<el-select v-model="brandId" filterable placeholder="请选择品牌" size="mini" remote clearable :remote-method="remoteMethod" v-on:change="ppChange" :loading="pploading">
   <el-option v-for="item in ppoptions"
              :key="item.id"
              :label="item.name"
              :value="item.id">
   </el-option>
</el-select>

函数方法部分的代码:

remoteMethod(query) {
  if (query !== '') {
  		//如果有输入值的话,则需要进行筛选
       this.pploading = true;
       clearTimeout(this.timer);
       this.timer = setTimeout(() => {
       		//输入框的内容为了防抖,则需要加个延迟,比如输入200毫秒后再触发筛选
           this.ppoptions = [];
           //此处先清空下拉列表,然后将已经选择的数据添加到ppoptions就是为了清除上次filter后的数据。
           if (this.brandId) {
               this.ppoptions = this.brandData.filter(b => {
                   return this.brandId.indexOf(b.id)>-1
               })
           }
           this.pploading = false;
           //下面的代码是筛选数据,根据输入的内容筛选,此时下拉列表中的数据为已经选择的内容+此次筛选的数据
           var ppoptions = this.brandData.filter(item => {
               return item.name.toLowerCase().indexOf(query.toLowerCase()) > -1;
           });
           //考虑到已经选择的内容,跟此次筛选的内容可能会有重复数据,因此需要数据的去重操作
           var dailiOptionsAll = ppoptions.concat(this.ppoptions);
           for (var i = 0; i < dailiOptionsAll.length; i++) {
               for (var j = i + 1; j < dailiOptionsAll.length; j++) {
                   if (dailiOptionsAll[i].id === dailiOptionsAll[j].id) {
                       dailiOptionsAll.splice(j, 1);
                       j = j - 1;
                   }
               }
           }
           this.ppoptions = ppoptions;
       }, 200);
   } else {
   	  //如果输入框中没有值,比如先输入内容而后删除输入内容,此时需要将筛选的无用数据清除,只保留已经选择的内容。
       this.ppoptions = [];
       if (this.brandId) {
           this.ppoptions = this.brandData.filter(b => {
               return this.brandId.indexOf(b.id) > -1
           })
       }
   }
},
//还有一种操作,就是如果选择了下拉列表中的内容后,也需要将筛选的内容清除,只保留已经选择的内容,以便于下次输入内容后筛选数据
 ppChange(e) {
    this.ppoptions = [];
    if (this.brandId) {
        this.ppoptions = this.brandData.filter(b => {
            return this.brandId.indexOf(b.id) > -1
        })
    }
}

还有一个特别需要注意的一点,那就是数据回填的时候,此时的下拉框中的数据ppotions应该是后端返回数据对应的参数。如果不进行处理的话,会发现数据回显的时候显示有误。

这个功能看上去很简单,但是实际使用的时候,很多需要考虑的点。

完成!!!