一、需求问题:

一开始就考虑使用简单el-select选取数据,但是后面数据量增多,

超过一千条开始,组件会很卡不好用,第二个是接口也慢了

数据量多的话是有一个filterable做支持了,可以输入关键字进行匹配检索

但是不能解决卡顿的问题,接口还是比较慢

二、替代方案:

然后改用了el-autocomplete组件,自动补全,在官网上是没有这个文档说明的

后来发现在el-input文档里面,el-input没有把这个组件拆出来说明。。。。

代码示例:

<el-form-item label="往来对象" prop="biRoObj" :style="commonStyle">
<el-autocomplete v-model.trim="form.biRoObjName" :fetch-suggestions="fetchArList" style="width: 100%;" :popper-append-to-body="false" :trigger-on-focus="false" placeholder="请先选择往来对象类型" @select="handleArSelect($event)" />
</el-form-item>

重要的几个参数:

v-model 等同el-input的一样就是输入值

fetch-suggestions 传递一个方法

@select 在选中选项时触发该事件, 传递一个事件方法

TriggerOnFocus 是否聚焦输入时触发搜索,建议关闭,默认输入完成时触发

FetchSuggestion用法:

/**
* fetchSuggestion
* 字面意思就是拉取建议选项,在输入关键字时触发该方法
* @param queryString 关键字,等同v-model值
* @param callBack 回调方法, 入参建议集合 [{ id: xx, value: xxx }]
*/
async fetchArList(queryString, callBack) {
/* 1、没有关键字时,返回空建议 */
if (!queryString) return callBack([{ id: '', value: '无结果' }])
/* 2、调用接口获取建议集合 */
await { data: arList } = await getArList({})
/* 3、如果没有建议,同理 */
if (arList.length === 0) return callBack([{ id: '', value: '无结果' }])
/* 4、做转换适配组件的属性要求,id和value */
const mapList = arList.map(x => { return { ... x, id: x.id, value: x.name } })
return callBack(mapList)
},

这里我是用promise的ES8语法同步化了一下

为了简洁语法就直接early return回调函数了

实际上是这样:

fetchArList(queryString, callBack) {
if (!queryString) {
callBack([{ id: '', value: '无结果' }])
// todo ...
} else {
getArList({}).then(res => {
const arList = res.data
if (arList.length === 0) {
callBack([{ id: '', value: '无结果' }])
} else {
const mapList = arList.map(x => { return { ... x, id: x.id, value: x.name } })
callBack(mapList)
}
}).catch(err => {
console.error(err)
// todo error ...
})
}
}

后台接口(Java):

这里有一个限制值,考虑到有可能用户输入的关键字还是会检索很多记录

就限制记录结果,迫使用户找不到后,提供更多关键字进行查找

这里我是按参数设置,如果不提供参数,默认50个以内

/**
* @author cloud9
* @date 2023/6/30 11:48
* @description 下拉集合检索用
* @params [dto]
* @return java.util.List
*/
@PostMapping("/list/forFetch")
public List<SysArEmployeeDTO> getSysArCustomerListForFetch(@RequestBody SysArEmployeeDTO dto) {
String lastLimit = "LIMIT " + (Objects.nonNull(dto.getPage()) ? dto.getPage().getSize() : 50);
return sysArEmployeeService
.lambdaQuery()
.select(SysArEmployeeDTO::getId, SysArEmployeeDTO::getEmCode, SysArEmployeeDTO::getEmName)
.and(wq -> wq.like(StringUtils.isNotBlank(dto.getEmName()), SysArEmployeeDTO::getEmCode, dto.getEmName())
.or().like(StringUtils.isNotBlank(dto.getEmName()), SysArEmployeeDTO::getEmName, dto.getEmName()))
.orderByDesc(SysArEmployeeDTO::getEmCode)
.last(lastLimit)
.list();
}

@select事件的处理:

1、事件方法会传递一个事件对象入参,该对象就是建议集合的元素,你放了什么属性,这个对象就能拿什么属性

2、除了赋值输入值以外,因为传递到后台存的是id值,所以需要把id赋值好,form校验的是id,所以两者的处理要同步

3、可以使用直接赋值,但是我没试过,可能是考虑组件有可能不监听数据变化,就用$set赋值刷新组件

4、这个事件等同el-select的@change事件,所以原来的业务逻辑@change有回调处理的时候,可以完全平滑迁移过来

handleArSelect(event) {
this.$set(this.form, 'biRoObj', event.id)
this.$set(this.form, 'biRoObjName', event.value)
}

  

数据回显问题:

回显时保持和输入值一致,查询的时候带上这个值返回到页面就可以了

这个组件和el-select一样,在定义的form表单对象中,一定要写默认值

不然就会无法输入,不能选择(踩过的坑)

三、校验补充:

因为不是像el-select那种change事件,它是自己输入的

在写完上面的例子后可以发现,我们清空了输入值,是不会触发表单校验的

因为id值没有被清空,所以我们需要通过使用watch监听变化来更新id值:

  watch: {
'form.biRoObjName': {
immediate: true,
handler() {
if (!this.form.biRoObjName) this.form.biRoObj = ''
}
}
}

这里不关心新值和旧值的对比处理,就不接参了(oldVal, newVal)

判断label值是否存在,不存在时同步更新id值,这样就能触发表单校验了

四、下拉样式调整:

这个下拉框的宽度是默认跟随input组件宽度的

在特殊情况下,建议选项的展示文本远远超出了组件宽度,默认下是省略的

所以需要强制调整宽度,展示更多文本内容

/* el-autocomplete组件 下拉框 设置 */
/deep/ .el-popper[x-placement^=bottom]{
width:400px !important;
text-align: left;
}

五、复杂业务的情况:

上面的情况是表单的单个属性的一个问题,在这里要处理的是一个集合的情况

<el-table-column prop="adTypeName" min-width="130px" align="center" label="归属项目" class-name="full-width">
<template slot-scope="sc">
<el-form-item :prop=" `tableData.${sc.$index}.adType`" :rules="rules.adType" :style="commonStyle">
<el-autocomplete v-model.trim="sc.row.prName" :disabled="projectLockFlag || !!sc.row.adServIdent" :fetch-suggestions="fetchPrList" style="width: 100%;" :popper-append-to-body="false" :trigger-on-focus="false" placeholder="输入归属项目" @select="handlePrSelect($event, sc.$index, sc.row)" />
</el-form-item>
</template>
</el-table-column>

首先是@Select事件的接参问题:

因为要处理集合的任意元素,方法需要知道元素,下标值,以及传递的值

1、可以用$event对象表示

@select="handlePrSelect($event, sc.$index, sc.row)"

2、使用箭头函数传递:

@select="(event) => handlePrSelect(event, sc.$index, sc.row)"

赋值时:

handlePrSelect(event, idx, row) {
this.$set(this.form.tableData[idx], 'adType', event.id)
this.$set(this.form.tableData[idx], 'prName', event.inName)
}

集合校验的问题:

因为集合不能监听每个元素,只能监听集合本身

注意这里要声明 deep: true,才会监听元素内部变化

不声明时,watch只关注集合的长度变化

watch: {
'form.tableData': {
deep: true,
immediate: true,
handler() {
this.form.tableData.forEach((el, idx, arr) => {
if (!el.prName) this.$set(arr[idx], 'adType', '')
})
}
}
},

  

六、Clearable不失焦的BUG:

参考方案:

https://zhuanlan.zhihu.com/p/395688018

每个autoComplete基本上都需要这么做

所以我干脆注册到原型对象里面,方便全局调用

import Vue from 'vue'

/**
* 修复el-autocomplete(clearable)清空后不能触发检索的问题
* 触发后手动调用失焦
*/
Vue.prototype.$clearForElAutoComplete = () => {
document.activeElement.blur()
}

在组件设置方法:

<el-col :span="8">
<el-form-item label="往来对象" prop="apReObj" :style="commonStyle">
<el-autocomplete v-model.trim="form.apReObjName" clearable :fetch-suggestions="fetchArList" style="width: 100%;" :popper-append-to-body="false" :trigger-on-focus="true" placeholder="请先选择往来对象类型" @clear="$clearForElAutoComplete" @select="handleArSelect($event)" />
</el-form-item>
</el-col>

  

2023年11月27日 21:34更新

功能思路:

最近开发的项目,用户反馈,检索的内容过多,可以拆分关键字,按多个关键字更精准定位内容

我想到一定有个分隔符,分割开每个关键词, 可以是空格、逗号、中文逗号

可以先替换成统一符号后转换成集合传给后台转换

SQL语句:

MySQL多关键字查询语句:

select * from user_info where address regexp '花园路|幸福路|安康路';

  

  

【Vue】el-select 数据过多替代方案的更多相关文章

  1. Vue框架(一)——Vue导读、Vue实例(挂载点el、数据data、过滤器filters)、Vue指令(文本指令v-text、事件指令v-on、属性指令v-bind、表单指令v-model)

    Vue导读 1.Vue框架 vue是可以独立完成前后端分离式web项目的js框架 三大主流框架之一:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定 ...

  2. vue ajax获取数据的时候,如何保证传递参数的安全或者说如何保护api的安全

    https://segmentfault.com/q/1010000005618139 vue ajax获取数据的时候,如何保证传递参数的安全或者说如何保护api的安全 点击提交,发送请求.但是api ...

  3. vue中<select>绑定事件

    <div id="app"> <select v-model="selectItem" @change="selectFn($eve ...

  4. vue中select设置默认选中

    vue中select设置默认选中 一.总结 一句话总结: 通过v-model来:select上v-model的值为option默认选中的那项的值(value) 二.select设置默认选中实例 < ...

  5. vue中select的使用以及select设置默认选中

    简介 今天写pc端引入vue,遇到了一个问题,就是我循环出select内的数据以后,发现原本默认显示第一条的select框变成了空白,要选择后才有显示,结果查了好多文档,讲的都不是很清楚,后来看到一句 ...

  6. vue中v-model 数据双向绑定

    表单输入绑定 v-model 数据双向绑定,只能应用在input /textare /select <div id="app"> <input type=&quo ...

  7. vue 组建实现数据的双向绑定

    <!DOCTYPE html><html><head> <style>body {  font-family: Helvetica Neue, Aria ...

  8. 查询数据过多页面反应慢引入缓存解决方案(Redis、H2)

      问题:原系统查询接口不支持分页也不可能加入分页支持,导致Ajax查询数据过多,返回数据达到2W多条记录时响应已经极慢,查询功能不要求数据实时性,页面反应速度极慢.体验不好:经排查是由于数据量过大导 ...

  9. vue+mockjs 模拟数据,实现前后端分离开发

    在项目中尝试了mockjs,mock数据,实现前后端分离开发. 关于mockjs,官网描述的是 1.前后端分离 2.不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据. 3.数据类型丰 ...

  10. 用vue写添加数据、删除数据、筛选数据表格

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

随机推荐

  1. Qt QMainWindow的使用

    参考视频:黑马科技:https://www.bilibili.com/video/BV1XW411x7NU?p=19 QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu b ...

  2. python-一种去掉前后缀获取子串的方法

    假设有一个字符串,其数据组成方式为:"mode_id1_str_id2",其中id1和id2为任意个数的数字,若存在mode,则id1必然也存在,否则都不存在:id2可有可没有. ...

  3. vue3项目安装依赖报错 npm ERR! code ERESOLVE

    vue3项目安装依赖报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While reso ...

  4. kettle从入门到精通 第三十二课 mysql 数据连接集群/分区配置

    1.这里的集群实际上是数据分区或者分片的概念,如中国全国的学生,应该不会都存在一张表里面,有可能每个省市一个表进行存储. 2.集群(分区),如下图所示 设置在"集群"标签,勾选&q ...

  5. C# .NET 压缩ZIP时 OOM OutOfMemoryException

    C# .NET 压缩ZIP时 OOM OutOfMemoryException. ZipArchiveEntry.ZipEntry.SharpZipLib.ZipOutputStream.OutOfM ...

  6. Ubuntu 更改鼠标滚轮速度

    1.安装imwheel sudo apt-get install imwheel 2.更改配置 sudo gedit ~/.imwheelrc 输入以下内容: ".*"None,  ...

  7. (一)requests-实战小练习

    1.需求:爬取豆瓣电影分类排行榜 https://movie.douban.com/中的电影详情数据 (此处以抓取科幻电影分类的信息为例) import requests import json ur ...

  8. 开源一款功能强大的 .NET 消息队列通讯模型框架 Maomi.MQ

    目录 文档说明 导读 快速开始 消息发布者 IMessagePublisher 连接池 消息过期 事务 发送方确认模式 独占模式 消费者 消费者模式 事件模式 分组 消费者模式 消费.重试和补偿 消费 ...

  9. Java8 - sum求和,将 List 集合转为 Map,key去重(groupingBy),sorted排序

    Java8 - sum求和,将 List 集合转为 Map,key去重(groupingBy),sorted排序 package com.example.core.mydemo.java8; publ ...

  10. MySQL Explain 关键字详解

    概述 explain 关键字可以模拟执行 sql 查询语句,输出执行计划,分析查询语句的执行性能 使用方式如下:explain + sql explain select * from t1 执行计划各 ...