当前位置: 首页 > news >正文

vue3——利用自定义指令实现下拉框分页懒加载

需求:下拉框一开始请求第一页的内容,滚动到最后的时候,请求第二页的内容,如此反复,直到所有数据加载完成。

selectLoadMore.ts

//自定义指令:实现下拉框下拉到末尾时,加载下一页的内容
// 使用时传两个参数,一个是下拉框的class,一个是下拉框滚动到末尾时触发的函数,比如:
// v-el-select-loadmore="{
//   selector: '.myOption .el-select-dropdown .el-select-dropdown__wrap',
//   loadFunction: loadMore
// }"
export default {mounted(el, binding) {//解构传来的值const {value: { selector, loadFunction }} = bindingconst SELECTWRAP_DOM = document.querySelector(selector)if (SELECTWRAP_DOM) {// 监听事件的处理函数,把函数单独写出来,方便销毁const scrollHandler = () => {const condition = SELECTWRAP_DOM.scrollTop + SELECTWRAP_DOM.clientHeight >= SELECTWRAP_DOM.scrollHeight - 1if (condition) {loadFunction()}}//赋值,为了方便销毁,这里很重要,不然销毁的时候找不到dom和对应的回调函数!!!el.dom = SELECTWRAP_DOMel.event = scrollHandler//监听滚动事件SELECTWRAP_DOM.addEventListener('scroll', scrollHandler)}},
//销毁,会在关闭弹窗时触发(这里的el-select写在弹窗里)beforeUnmount(el) {if (el.dom) {el.dom.removeEventListener('scroll', el.event)}}
}

记得在main.ts里面注册成全局组件!!!! 

main.ts

import vElSelectLoadmore from '@/utils/tools/selectLoadMore'
app.directive('el-select-loadmore', vElSelectLoadmore) //全局自定义指令
app.mount('#app')

使用的vue文件 

//使用时在指令里传值,这里有个坑!
//在el-select给一个参数popper-class="myOption",因为element-plus中ei-select的选项是使用的popper.js生成的,无法直接获取,直接获取下拉框的dom获取不到<el-selectv-el-select-loadmore="{selector: '.myOption .el-select-dropdown .el-select-dropdown__wrap',loadFunction: loadMore}"v-model="userForm.accountName"placeholder="请选择用户"popper-class="myOption"><el-optionv-for="(item, index) in userData"v-loading="optionLoading(index)":key="item.id":label="item.username":value="item.id"/></el-select>//总共的数据条数
let totalCount: number = 0
//当前滚动页
let page: number/*** 自定义指令触发的回调*/
function loadMore() {//计算总页数let maxPagSize: number = Math.max(Math.ceil(totalCount / 10), 1)//不超过总页数才发请求if (page < maxPagSize) {page += 1//发请求,获得接口数据getUserListWrap(page, 10)}
}/*** 控制下拉框loding是否出现,isOptionLoading是在getUserListWrap请求函数里面的,userData是请求函数获得是下拉框数据,这样可以使下拉到最后一个option的时候,出现loding效果,更加完善美观* @param index 下拉框循环的index*/
function optionLoading(index: number): boolean {if (isOptionLoading.value && index == userData.length - 1) {return true} else {return false}
}

总结:

1、 在el-select给一个参数popper-class="myOption",因为element-plus中el-select的选项是使用的popper.js生成的,无法直接获取,直接获取下拉框的dom获取不到

2、在自定义指令里面销毁事件的时候,在mounted必须把事件存在el上,不然不好销毁,一开始是以下这么写的:发现这样不好销毁,因为在 beforeUnmount拿不到function,this只能按以下这么写才行,如果单独把funtion拎出来,this就报错找不到

export default {mounted(el, binding) {const {value: { selector, loadFunction }} = bindingconst SELECTWRAP_DOM = document.querySelector(selector)if (SELECTWRAP_DOM) {SELECTWRAP_DOM.addEventListener('scroll', function () {const condition = this.scrollTop + this.clientHeight >= this.scrollHeight - 1if (condition) {loadFunction()}})}}
}

 vue3的demo代码如下:

<template><el-form-item label="用户名称:"><el-select popper-class="myOption"v-model="accountName" placeholder="请输入或选择用户"  v-el-select-loadmore="loadMore"><el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
</template><script setup lang="ts">
import {ref,onMounted} from 'vue'
let page = ref(1)
let pageSize = ref(10)
let total = 100
let totalCount=6
let stopLoading = false
let accountName = ref('')
const options = ref([])
onMounted(() => {options.value.length=0loadOptions(1)
})function loadMore() {//这里设置接口的最大页数totalCount为6,超过6页就没数据了if (page.value <= totalCount) {page.value += 1;//获得接口数据loadOptions(page.value);}}function loadOptions(page:number) {// 模拟接口发送数据,异步加载数据setTimeout(() => {for (let i = (page-1)*10+1; i <= page*10; i++) {options.value.push({value: `Option${i}`,label: `Option${i}`});}}, 500);
}
//在自定义指令
const vElSelectLoadmore = {mounted(el: any, binding: any) {// 坑:const SELECTWRAP_DOM:Element|null = document.querySelector('.myOption .el-select-dropdown .el-select-dropdown__wrap');if (SELECTWRAP_DOM) {SELECTWRAP_DOM.addEventListener('scroll', function () {const condition = this.scrollTop+this.clientHeight >= this.scrollHeight-1;// 当滚动条滚动到最底下的时候执行接口加载下一页if (condition) {binding.value && binding.value()}});}},}</script>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 前端模块化CommonJS、AMD、CMD、ES6
  • MYSQL(2) 高级查询
  • sql注入 mysql 执行命令 sql注入以及解决的办法
  • C语言 #具有展开功能的排雷游戏
  • WHAT - 不同 HTTP Methods 使用场景、使用方法和可能遇到的问题
  • 力扣1089复写0
  • JVM 性能分析—— 一文带你读懂 G1 垃圾收集器收集流程
  • 鸿蒙应用框架开发【OpenGL三棱椎】 NDK
  • postgres数据库连接超时问题处理
  • ArcGIS Pro SDK (九)几何 17 几何引擎函数
  • @Builder注释导致@RequestBody的前端json反序列化失败,HTTP400
  • C# 委托函数 delegate
  • 基于C语言从0开始手撸MQTT协议代码连接标准的MQTT服务器,完成数据上传和命令下发响应(华为云IOT服务器)
  • PyQt ERROR:ModuleNotFoundError: No module named ‘matplotlib‘
  • Google Test 学习笔记(简称GTest)
  • Android Studio:GIT提交项目到远程仓库
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • ES学习笔记(12)--Symbol
  • Facebook AccountKit 接入的坑点
  • Mocha测试初探
  • PAT A1120
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vultr 教程目录
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 简单数学运算程序(不定期更新)
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 浅谈Golang中select的用法
  • 为视图添加丝滑的水波纹
  • 一起参Ember.js讨论、问答社区。
  • 用element的upload组件实现多图片上传和压缩
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • # wps必须要登录激活才能使用吗?
  • #laravel 通过手动安装依赖PHPExcel#
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $.ajax()方法详解
  • (二)windows配置JDK环境
  • (二十三)Flask之高频面试点
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (实战篇)如何缓存数据
  • (转)Linq学习笔记
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .NET 使用配置文件
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】
  • .net的socket示例