实现Dropdown下拉菜单监听键盘上下键选中功能-React

本文主要是介绍实现Dropdown下拉菜单监听键盘上下键选中功能-React,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用过ant design的小伙伴都知道,select组件是支持联想搜索跟上下键选中的效果的,但是在项目中我们可能会遇到用select组件无法实现我们的需求的情况,比如说一个div框,里面有input,又有tag标签,在input中输入内容触发联想,然后选中其中某一个,以tag标签的形式回填到div框中(类似这种需求)。这个时候,我们可以采用ant design的dropdown组件来帮助我们实现。

getBoundingClientRect()方法可以获取元素的大小及其相对视口的位置,这样可以帮助对元素是否在可视区域内进行判断

getBoundingClientRect() 是一个在 DOM(文档对象模型)中常用的方法,它返回一个 DOMRect 对象,
该对象提供了元素的大小及其相对于视口的位置。这个方法非常有用,
特别是在需要知道元素在页面上的确切位置或尺寸时。DOMRect 对象包含以下属性:x:元素左上角相对于视口(viewport)的 x 坐标(包括任何滚动偏移)。
y:元素左上角相对于视口(viewport)的 y 坐标(包括任何滚动偏移)。
width:元素的宽度(包括内边距 padding,但不包括边框 border、外边距 margin 和滚动条)。
height:元素的高度(包括内边距 padding,但不包括边框 border、外边距 margin 和滚动条)。
top:元素顶部边缘相对于视口(viewport)的 y 坐标(包括任何滚动偏移)。
right:元素右边缘相对于视口(viewport)的 x 坐标(包括任何滚动偏移)。
bottom:元素底部边缘相对于视口(viewport)的 y 坐标(包括任何滚动偏移)。
left:元素左边边缘相对于视口(viewport)的 x 坐标(包括任何滚动偏移)。

页面布局代码 ,需要根据实际情况来进行调整

componentDidMount(){// 添加键盘事件监听  document.addEventListener('keydown', this.handleKeyDown);
}// 渲染下拉项
showGroupContcatMenu = ()=>{const {contactSearchList, currentFocusMenuIndex} = this.state;return <Menu>{contactSearchList.map((item, index)=>(<Menu.Item id={"dropdown-menu-item-" + index} key={item.id} onClick={()=>this.handleSelectMenuItem(item)} style={{background: index == currentFocusMenuIndex ? '#fff5e6' : ''}}><div>{item.name}&nbsp;&nbsp;{item.enterpriseName}&nbsp;&nbsp;<span>{item.email && `<${item.email}>`}</span></div></Menu.Item>))}<Menu.Item id={"dropdown-menu-item-" + contactSearchList.length} key={contactSearchList.length} style={{background: currentFocusMenuIndex == contactSearchList.length ? '#fff5e6' : ''}} onClick={()=>this.openGroupContcatIcon(null)}>搜索联系人</Menu.Item></Menu>}// 布局代码
<div className="tag">{selectContact.length > 0 && selectContact.map(item=>(<Popover key={item.id} trigger="click" content={<Spin spinning={showPhoneLoading}><span style={{userSelect:'none'}}>{showPhoneLoading?'':trueEmail}</span></Spin>} overlayClassName='contact-email-tip'onVisibleChange={(visible) => this.onPopoverVisibleChange(visible, item)}><Tag key={item.id} closable={true} onClose={(e)=>this.handleClose(item.id,item,e,'searchGroupContcat','contact')}>{item.name}{item.hiddenEmail || item.email || item.disPlayEmail?<span>&nbsp;&nbsp;</span>:''}{item.hiddenEmail || item.email || item.disPlayEmail}</Tag></Popover>))}<Dropdown visible={onKeywordsContact ? true : false}overlay={()=>this.showGroupContcatMenu()} overlayClassName='bropdown-overlay-class'destroyPopupOnHide={true} ><div>{getFieldDecorator('onKeywordsContact', {initialValue: '',})(<AInput className="input" onBlur={(e)=>this.handleBlur('onKeywordsContact')}onPressEnter={this.handleInputPressEnter}onChange={this.handleGroupContcatChange}/>)}</div></Dropdown>
</div>

监听键盘响应事件的核心代码

handleKeyDown = (event) =>{const {onKeywordsContact, currentFocusMenuIndex, contactSearchList} = this.statelet newCurrentFocusMenuIndex = currentFocusMenuIndex;if (event.key === 'ArrowUp' && onKeywordsContact) {  event.preventDefault(); newCurrentFocusMenuIndex = currentFocusMenuIndex <= 0 ? contactSearchList.length : currentFocusMenuIndex - 1;this.scrollIntoViewIfNeeded(newCurrentFocusMenuIndex, contactSearchList.length);} else if (event.key === 'ArrowDown' && onKeywordsContact) {  event.preventDefault();  newCurrentFocusMenuIndex = currentFocusMenuIndex >= contactSearchList.length ? 0 : currentFocusMenuIndex + 1;this.scrollIntoViewIfNeeded(newCurrentFocusMenuIndex, contactSearchList.length);}  this.setState({currentFocusMenuIndex: newCurrentFocusMenuIndex // 记录当前选中高亮的元素}) }scrollIntoViewIfNeeded = (newCurrentFocusMenuIndex, maxLength)=>{const ulEle = $('.bropdown-overlay-class .ant-dropdown-menu')[0];const liEle = $('#dropdown-menu-item-' + newCurrentFocusMenuIndex)[0];const ulRect = ulEle.getBoundingClientRect();  const liRect = liEle.getBoundingClientRect();if(newCurrentFocusMenuIndex == 0){ulEle.scrollTop = 0;} else if(newCurrentFocusMenuIndex == maxLength){ulEle.scrollTop = ulEle.scrollHeight;} else {// 检查li是否在ul的上方  if (liRect.top < ulRect.top) {  // 滚动ul到li的顶部位置  ulEle.scrollTop = liEle.offsetTop;  }  // 检查li是否在ul的下方(这里假设我们不想滚动超过li的底部)  else if (liRect.bottom > ulRect.bottom) {  // 滚动ul到li的底部位置减去ul的高度,以确保li的底部在可视区域内  ulEle.scrollTop = liEle.offsetTop + liEle.offsetHeight - ulEle.offsetHeight;   }  }}

这篇关于实现Dropdown下拉菜单监听键盘上下键选中功能-React的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1020691

相关文章

C#借助Spire.XLS for .NET实现在Excel中添加文档属性

《C#借助Spire.XLSfor.NET实现在Excel中添加文档属性》在日常的数据处理和项目管理中,Excel文档扮演着举足轻重的角色,本文将深入探讨如何在C#中借助强大的第三方库Spire.... 目录为什么需要程序化添加Excel文档属性使用Spire.XLS for .NET库实现文档属性管理Sp

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Python实现快速扫描目标主机的开放端口和服务

《Python实现快速扫描目标主机的开放端口和服务》这篇文章主要为大家详细介绍了如何使用Python编写一个功能强大的端口扫描器脚本,实现快速扫描目标主机的开放端口和服务,感兴趣的小伙伴可以了解下... 目录功能介绍场景应用1. 网络安全审计2. 系统管理维护3. 网络故障排查4. 合规性检查报错处理1.

Python轻松实现Word到Markdown的转换

《Python轻松实现Word到Markdown的转换》在文档管理、内容发布等场景中,将Word转换为Markdown格式是常见需求,本文将介绍如何使用FreeSpire.DocforPython实现... 目录一、工具简介二、核心转换实现1. 基础单文件转换2. 批量转换Word文件三、工具特性分析优点局

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位

Java使用Spire.Barcode for Java实现条形码生成与识别

《Java使用Spire.BarcodeforJava实现条形码生成与识别》在现代商业和技术领域,条形码无处不在,本教程将引导您深入了解如何在您的Java项目中利用Spire.Barcodefor... 目录1. Spire.Barcode for Java 简介与环境配置2. 使用 Spire.Barco

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求