elementplus 二次封装 select 自定义指令上拉加载更多 完美解决 多次接口调用 重新加载数据多次调用数据!!!

效果:(名字都是测试数据 随便乱写的 若有冒犯 请联系)

select 二次封装

网上的这种自定义指令上拉加载更多的实例有很多,但是基本都是有缺陷和问题的。为了记录这个问题 我研究了一天,在今天终于搞定了 呜呜呜。

网上遇到的问题:

1、封装的自定义指令没法用(后续会讲解原理)

2、封装完 select 之后 如果一个页面有多个封装的 select 会导致多次触发加载更多。比如一个页面有3个 select 其中一个触发了加载更多 则其他两个也会同时触发(如果是调接口则会触发三次)(后续会讲解原理)

3、当上拉触底多次(比如调用接口可能是 pageindex:1, pageindex:2, pageindex:3 获取三次的数据),这个时候点击其他区域 将 option 隐藏起来 这时候重新点击 select 会重新触发三次的接口请求。(后续会讲解原理)

开始二次封装 selec 组件(只写重点代码其他自己参考)

"element-plus": "^2.8.0",
"vue": "^3.2.47",

1、子组件

1、components/el-load-search-select/index.vue

<template><!-- :popper-class-name 和 :popper-class 和 v-loadmore 为这里的重点!!!!--><el-select:popper-class-name="popperClassName"v-model="selectedValue"v-loadmore="handleLoadMore"placeholder="请选择":popper-class="popperClassName":multiple="!isOnlySingle"collapse-tagsreserve-keywordv-bind="$attrs":teleported="true"filterableremote:remote-method="handleRemoteMethod"@visible-change="handleVisibleChange"@change="onSelectChange"><el-option v-if="isShowAll" label="全部" value=""></el-option><!-- :label="item.Name" --><el-optionv-for="item in baseSelectUserList":key="item.Id":label="item.Name":value="item[keyName]"><span style="float: left">{{ item.Name }}</span><span style="float: right; color: #8492a6; font-size: 13px">{{onShowLabel(item)}}</span></el-option></el-select>
</template>
<script setup lang="ts">const props = defineProps({/** 双向绑定 */modelValue: {type: [String, Array as () => Array<string>],default: null,},/** 机构参数 */orgIds: {type: [String, Array as () => Array<string>],default: "",},/** 科室参数 */deptIds: {type: [String, Array as () => Array<string>],default: "",},/** 角色 */roleTypes: {type: [String, Array as () => Array<string>],default: "",},/** 是否获取权限内的数据 */scopeable: {type: Boolean,default: false,},/** 是否是通过redash */isRedash: {type: Boolean,default: false,},/** 选择的是否是单选 */isOnlySingle: {type: Boolean,default: true,},/** 双向绑定的值是哪个字段 */keyName: {type: String,default: "Id",},/** 关键字搜索默认数据 */remoteName: {type: String,default: "",},/** dtoType */dtoTypeName: {type: String,default: "QueryUserOutputDto3",},/** 下拉列表显示什么数据 */selectShowLabel: {type: String,default: "",},/** 是否显示全部选择 */isShowAll: {type: Boolean,default: true,},/** 是否显示默认列表数据(主要是做回显操作) */isUseDefaultList: {type: Boolean,default: false,},/** 一个页面多次使用 select popperClassName不能重复 切记!!!!!!  */popperClassName: {require: true,type: String,},
});
</script>

2、父组件

<el-load-search-selectv-model="transferAssistant.oldPhone"placeholder="请选择医助":role-types="['doctor']":scopeable="false":is-redash="false":is-only-single="true"key-name="PhoneNumber"popper-class-name="oldAssistant" // 这里是重点style="width: 140px;"/>

3、自定义指令

src/directive/elSelectLoadMore.ts

import { debounce, DebouncedFunc } from "lodash";
export default {mounted(el: any, binding: { value: () => void; },vnode:any) {console.log('el', el)// 这里的popper-class-name就是使用 select 时候传递的 popper-class-name="oldAssistant" !!!!!const popperClassName = el.getAttribute('popper-class-name')console.log('popperClassName', popperClassName);let scrollWrap = document.querySelector(`.${popperClassName} .el-select-dropdown__wrap`)!// let scrollWrap = document.querySelector('.selectPopperClass .el-select-dropdown__wrap')!// 把监听的方法防抖一下const handle = debounce((e) => {console.log('scrollWrap.scrollTop', scrollWrap.scrollTop);console.log('scrollWrap.scrollHeight', scrollWrap.scrollHeight);console.log('scrollWrap.clientHeight', scrollWrap.clientHeight);let scrollDistance = scrollWrap.scrollHeight - scrollWrap.scrollTop// 比如此处预留10个像素的位置用于触底if (scrollWrap.clientHeight + 10 > scrollDistance) {binding.value() // 触底通知一下,外界}}, 170)// 绑定监听滚动事件scrollWrap?.addEventListener('scroll', handle)// 方法挂载到元素身上便于解绑时使用el._hanlde = handle},unmounted(el: { _hanlde: EventListenerOrEventListenerObject | null; }, binding: any) {let scrollWrap: any = document.querySelector('.el-scrollbar__wrap')console.log('scrollWrap', scrollWrap)scrollWrap?.removeEventListener('scroll', el._hanlde)el._hanlde = null}
}

src/directive/index.ts

import loadmore from "./elSelectLoadMore";
// 自定义指令对象,用于遍历注册
const directives = {loadmore,
} as any;
// 批量注册指令并暴露到main.js中去便于注册
export default {install(app: { directive: (arg0: string, arg1: any) => void }) {Object.keys(directives).forEach((key) => {app.directive(key, directives[key]);});},
};

src/mian.ts

import directive from './directive';
app.use(directive);

上面是所有的代码,接下来讲解上面的三个问题

三个问题的讲解

1、 封装的自定义指令没法用

原因出在let scrollWrap = document.querySelector()! 时候里面写的 class 实际在 dom 中不存在

在 elementplus 时候 select 进行了重构 element 的封装不适合了

2、封装完 select 之后 如果一个页面有多个封装的 select 会导致多次触发加载更多

这里的 select 是在 body 上面的 里面的 class 名称都是一样的 如果你  let scrollWrap = document.querySelector()!里面写的 class 名称是一样的话 就是导致这个问题

因为你每一个都是相同的 class 都回触发自定义指令

而我这边是自己传入了一个自定义属性(上面框起来 有 oldAssistant 和 newAssistant) 通过querySelector(自定义属性)! 那就每一个select不一样了

所以为什么我很强调popper-class-name="" 使用组件的这个属性为什么一定要不一样

3、点击其他区域 将 option 隐藏起来 这时候重新点击 select 会重新触发多次请求

在之前可能你请求了三次 数据可能有100条  假设每一条高度是20px 这时候你的整体高度就是2000px  这个时候你重新点击 select  又去加载数据(远程搜索 空字符串)可能只有30条 这个时候高度就是600px 那么之前的滚动条是在最底部的 elementplus 记录了你上一次的位置 这次你的高度只有600px 完全没有到达之前的高度 就会导致一直触发上拉触底 一直等到你的高度>=2000px的时候才会停止(以上只是推理 没有验证)

完美收官!! 若有问题 下方评论哦 对你有用是我最大的荣幸

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400807.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TSP-Detection:CMU 提出抛弃交叉注意力的 DETR 变体 | ICCV 2021

DETR基于Transformer将目标检测视为集合预测问题&#xff0c;实现了最先进的性能&#xff0c;但需要超长的训练时间才能收敛。论文研究了DETR优化困难的原因&#xff0c;揭示了收敛缓慢因素主要是匈牙利损失和Transformer交叉注意机制。为了克服这些问题&#xff0c;论文提出了…

微信小程序--26(全局配置-1)

一、全局配置文件 1.标志 app.json 2.配置项 pages 记录当前小程序所有页面的存放路径 window 全局配置小程序窗口配置 tabBar 设置小程序底部的tabBar效果 style 是否启用新版本的组将样式 3.window 导航栏区域 navigationBar …

11 Linux 设备驱动

11 Linux 设备驱动 1、Linux软件特点1.1 用户空间1.2 内核空间 2、Linux程序2.1 应用程序2.2 内核程序2.2.1 编程2.2.2 编译 2.3 内核命令行传参2.3.1 应用程序的命令行传参2.3.2 内核程序命令行传参 2.4 内核程序符号导出2.4.1 应用程序多文件之间的访问调用2.4.1 内核多文件之…

1Panel应用推荐:KubePi开源Kubernetes管理面板

1Panel&#xff08;github.com/1Panel-dev/1Panel&#xff09;是一款现代化、开源的Linux服务器运维管理面板&#xff0c;它致力于通过开源的方式&#xff0c;帮助用户简化建站与运维管理流程。为了方便广大用户快捷安装部署相关软件应用&#xff0c;1Panel特别开通应用商店&am…

H7-TOOL混合脱机烧录以及1拖4不同的通道烧录不同的程序操作说明(2024-08-07)

【应用场景】 原本TOOL的1拖4是用于同时烧录相同程序给目标板&#xff0c;但有时候一个板子上有多个不同的MCU&#xff0c; 客户希望仅通过一个TOOL就可以完成对板子上多个MCU的烧录&#xff0c;也就是1拖4不同的通道烧录不同的程序&#xff0c;此贴为此制作。 【实验目标】…

序列建模之循环和递归网络 - 循环神经网络篇

序言 在探索序列数据的深层规律时&#xff0c;循环神经网络&#xff08; RNN \text{RNN} RNN&#xff09;以其独特的设计思想成为了序列建模领域的中流砥柱。与传统的神经网络不同&#xff0c; RNN \text{RNN} RNN引入了循环结构&#xff0c;使得网络能够处理任意长度的序列数…

winform 大头针实现方法——把窗口钉在最上层

平时我们再使用成熟的软件的时候&#xff0c;会发现有个大头针的功能挺不错的。就是点一下大头针&#xff0c;窗口就会钉住&#xff0c;一直保持在最上面一层&#xff0c;这样可以一边设置参数&#xff0c;一边观察这个窗口里面的变化&#xff0c;比较方便。下面我就来简单实现…

移动APP测试有哪些注意事项?专业APP测试报告如何获取?

移动APP在其生命周期中有不同的阶段&#xff0c;从开始到投入目标市场再到被淘汰。移动APP的成功有多种因素&#xff0c;例如创建、部署、推广、粘性等。但是&#xff0c;创建出色APP的关键在于它的测试&#xff0c;软件测试负责为客户提供安全有效的产品&#xff0c;因此移动A…

大数据-83 Spark 集群 RDD编程简介 RDD特点 Spark编程模型介绍

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

Golang 与 Java:编程语言比较及如何选择

Golang 与 Java&#xff1a;哪种语言更好&#xff1f;我们的详细比较指南涵盖了语法、性能和流行度方面的主要差异&#xff0c;以帮助您做出决定。 在规划项目时&#xff0c;有许多编程语言可供选择。但一开始就选择正确的语言是成功启动或交付的关键。选择错误的语言&#xff…

Apache Tomcat 信息泄露漏洞排查处理CVE-2024-21733)

一、漏洞描述 Apache Tomcat作为一个流行的开源Web服务器和Java Servlet容器并用于很多中小型项目的开发中。其中,Coyote作为Tomcat的连接器组件,是Tomcat服务器提供的供客户端访问的外部接口,客户端通过Coyote与服务器建立链接、发送请求并且接收响应。 近日发现Apache To…

【python】OpenCV—Optical Flow

文章目录 1、光流2、Opencv 中光流的实现3、稀疏光流4、密集光流4.1、farneback4.2、lucaskanade_dense4.3、rlof 5、涉及到的库5.1、cv2.goodFeaturesToTrack5.2、cv2.calcOpticalFlowPyrLK5.3、cv2.optflow.calcOpticalFlowSparseToDense5.4、cv2.calcOpticalFlowFarneback5.…

CentOS7.9上通过KVM安装Centos虚拟机

目录 1 开发前准备&#xff08;先确保服务器可以虚拟化&#xff09;&#xff1a; 2、安装KWM环境 3、创建镜像文件存放目录 4、创建镜像文件存放目录 5、安装桥连接虚拟网络 6、安装虚拟机 7、配置操作系统 8、虚拟机配置网卡地址 9、克隆虚拟机执行 1开发前准备&am…

Unity教程(十)Tile Palette搭建平台关卡

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

IDEA 创建类时自动生成注释

一、背景 在开发的过程中&#xff0c;公司都会要求开发针对自己创建的类进行一些描述说明&#xff0c;为了便于程序员在创建类时快速生成注释。 二、如何配置? 打开File -> Settings -> Editor -> File and Code Templates -> Includes&#xff0c;在File Header…

Unity新输入系统结构概览

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 在学习新输入系统之前&#xff0c;我们需要对其构成有个印象 1.输入动作&#xff08;Inputaction&#xff09; 是定义输…

一次caffeine引起的CPU飙升问题

背景 背景是上游服务接入了博主团队提供的sdk&#xff0c;已经长达3年&#xff0c;运行稳定无异常&#xff0c;随着最近冲业绩&#xff0c;流量越来越大&#xff0c;直至某一天&#xff0c;其中一个接入方&#xff08;流量很大&#xff09;告知CPU在慢慢上升且没有回落的迹象&…

2分钟搭建一个简单的WebSocket服务器

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注。个人知乎 如何用2分钟在本地搭建一个简单的 WebSocket 服务器&#xff1f;其实使用 Node.js&#xff0c;加上一些流行的库&#xff0c;是很容易实现的。前端同学通过自己搭建 WebSocket 服务器&#xff0c;对于…

百问网全志系列开发板音频ALSA配置步骤详解

8 ALSA 8.1 音频相关概念 ​ 音频信号是一种连续变化的模拟信号&#xff0c;但计算机只能处理和记录二进制的数字信号&#xff0c;由自然音源得到的音频信号必须经过一定的变换&#xff0c;成为数字音频信号之后&#xff0c;才能送到计算机中作进一步的处理。 ​ 数字音频系…

系统重装简记

写在文章开头 因为固态损毁而更换固态&#xff0c;所以需要进行系统重装&#xff0c;由于系统重装都是固定的繁琐的步骤&#xff0c;所以就以这篇文章来记录一下系统重装的一些日常步骤&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核…