一、需求问题:

一开始就考虑使用简单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. Tkinter界面实操

    常用opencv-python进行图像处理,有时需要图形用户界面,写个Demo以备不时之需. Tkinter 1. 导入库 由于 Tkinter 是内置到 python 的安装包中.只要安装好 Pyt ...

  2. redis自动化安装

    1.ruby脚本自动化安装 1.安装ruby开发环境 yum install rubygems -y 2.通过ruby包管理工具,安装操作redis的模块 gem sources --remove h ...

  3. reactHooks的组件通信

    父组件调用子组件的方法 // 父组件 import React, { useEffect, useRef, useState } from 'react'; import StopModal from ...

  4. fs.1.10 ON rockeylinux8 dockerfile模式

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. rockeylinux8 docker上编译安装fs.1.10的流程记录,本文使用dockerfile模式. 环境 docker e ...

  5. MySQL查询关于区分字母大小写问题

    前段时间在工作中测试提出了一个BUG,让我把根据ID查询区分大小写的功能去掉,大小写都随便查,然后我在SQL的位置加上了UPPER(id) = UPPER(#{id})的写法,而同事知道这个问题后的反 ...

  6. OpenCV + sklearnSVM 实现手写数字分割和识别

    这学期机器学习考核方式以大作业的形式进行考核,而且只能使用一些传统的机器学习算法. 综合再三,选择了自己比较熟悉的MNIST数据集以及OpenCV来完成手写数字的分割和识别作为大作业. 1. 数据集准 ...

  7. 05-CentOS防火墙

    概述 CentOS中的防火墙有很多,如SELinux.Firewall.TCP Wrappers.iptables/netfilter. 每种防火墙都有各自擅长的地方. 这里主要讲两种:SELinux ...

  8. 【资料分享】全志科技T507工业核心板硬件说明书(下)

    目    录 3 电气特性 3.1 工作环境 3.2 功耗测试 3.3 热成像图 4 机械尺寸 5 底板设计注意事项 5.1 最小系统设计 5.1.1 电源设计说明 5.1.2 系统启动配置 5.1. ...

  9. power bi权限控制笔记

    power bi权限控制:power bi权限控制角色目前只能在desktop 客户端进行创建.报表进行权限控制后,用于行级别安全,需注意:a.对数据集做行级别安全性的角色分配 b.需要进行报表的共享 ...

  10. SpringBoot AOP完美记录用户操作日志,附源码

    记录内容 接口名称 浏览器名称 操作系统 请求ip 接口入参.出参 接口耗时 .... 表结构 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- -- ...