不可不知的react模糊搜索与结果高亮
前言
随着vue
、react
等框架等广泛使用,前端对数据处理的需求越来越多,处理的数据量也越来越大。今天我就接到这么一个需求,为了减少对后端的请求次数,提高性能,前端实现对数据进行轻量的模糊搜索与检索结果的高亮显示。talk is cheap,show me code
,咱们闲话少说,直接看demo
代码(这里我们使用模糊检索antd
中的icon
图标做demo
演示):
如下是App.tsx
文件内容:
// App.tsx
import React, { useState } from 'react';
import { Icon, Input } from 'antd';
import './App.css';const icons = ['step-backward','step-forward','fast-backward','fast-forward','shrink','arrows-alt','down','up','left','right','caret-up','caret-down','caret-left','caret-right','up-circle','down-circle','left-circle','right-circle','up-circle-o','down-circle-o','right-circle-o','left-circle-o','double-right','double-left','forward','backward','rollback','enter','retweet','swap','swap-left','swap-right','arrow-up','arrow-down','arrow-left','arrow-right','play-circle','play-circle-o','up-square','down-square','left-square','right-square','up-square-o','down-square-o','left-square-o','right-square-o','login','logout','menu-fold','menu-unfold','question','question-circle-o','question-circle','plus','plus-circle-o','plus-circle','pause','pause-circle-o','pause-circle','minus','minus-circle-o','minus-circle','plus-square','plus-square-o','minus-square','minus-square-o','info','info-circle-o','info-circle','exclamation','exclamation-circle-o','exclamation-circle','close','close-circle','close-circle-o','close-square','close-square-o','check','check-circle','check-circle-o','check-square','check-square-o','clock-circle-o','clock-circle','warning','lock','unlock','area-chart','pie-chart','bar-chart','dot-chart','bars','book','calendar','cloud','cloud-download','code','code-o','copy','credit-card','delete','desktop','download','edit','ellipsis','file','file-text','file-unknown','file-pdf','file-word','file-excel','file-jpg','file-ppt','file-markdown','file-add','folder','folder-open','folder-add','hdd','frown','frown-o','meh','meh-o','smile','smile-o','inbox','laptop','appstore-o','appstore','line-chart','link','mail','mobile','notification','paper-clip','picture','poweroff','reload','search','setting','share-alt','shopping-cart','tablet','tag','tag-o','tags','tags-o','to-top','upload','user','video-camera','home','loading','loading-3-quarters','cloud-upload-o','cloud-download-o','cloud-upload','cloud-o','star-o','star','heart-o','heart','environment','environment-o','eye','eye-o','camera','camera-o','save','team','solution','phone','filter','exception','export','customer-service','qrcode','scan','like','like-o','dislike','dislike-o','message','pay-circle','pay-circle-o','calculator','pushpin','pushpin-o','bulb','select','switcher','rocket','bell','disconnect','database','compass','barcode','hourglass','key','flag','layout','printer','sound','usb','skin','tool','sync','wifi','car','schedule','user-add','user-delete','usergroup-add','usergroup-delete','man','woman','shop','gift','idcard','medicine-box','red-envelope','coffee','copyright','trademark','safety','wallet','bank','trophy','contacts','global','shake','api','fork','dashboard','form','table','profile','android','android-o','apple','apple-o','windows','windows-o','ie','chrome','github','aliwangwang','aliwangwang-o','dingding','dingding-o','weibo-square','weibo-circle','taobao-circle','html5','weibo','twitter','wechat','youtube','alipay-circle','taobao','skype','qq','medium-workmark','gitlab','medium','linkedin','google-plus','dropbox','facebook','codepen','amazon','google','codepen-circle','alipay','ant-design','aliyun','zhihu','slack','slack-square','behance','behance-square','dribbble','dribbble-square','instagram','yuque',
];function App() {const [iconList, setIconList] = useState(icons);const [keyWord, setKeyWord] = useState('');const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {const search = e.target.value;setIconList(search ? (icons.filter(type => type.includes(search))) : icons);setKeyWord(search);};const renderIconType = (iconType: string, search: string) => {if (!search) return iconType;const reg = new RegExp(search, 'ig');const splitIconTypes = iconType.split(reg);const matchIconTypes = iconType.match(reg) as Array<string>;return (<React.Fragment>{matchIconTypes.map((_, index) => {return (<React.Fragment key={ index }><span>{ splitIconTypes[index] }</span><span className="icon-mark">{ matchIconTypes[index] }</span></React.Fragment>)})}<span>{ splitIconTypes[splitIconTypes.length - 1] || '' }</span></React.Fragment>)};return (<div className="App"><header className="App-header"><Input.Search placeholder="请输入" addonBefore="请输入关键字" value={ keyWord } onChange={ handleSearch } allowClear /></header><div><ul className="icon-list">{iconList.map((iconType) => {return (<li className="icon-item" key={ iconType }><Icon className="icon" type={ iconType } /><p>{ renderIconType(iconType, keyWord) }</p></li>)})}</ul></div></div>);
}export default App;
如下是App.css
文件内容:
// App.css
@import '~antd/dist/antd.css';.App {padding: 15px;
}.App-header {width: 30%;margin: 0 auto;
}.icon-list {list-style: none;margin: 10px 0;display: grid;grid-template-columns: repeat(8, 1fr);grid-column-gap: 10px;align-items: center;justify-content: center;
}.icon-item {display: flex;flex-direction: column;justify-content: center;align-content: center;margin: 10px;
}.icon > svg {width: 30px;height: 30px;
}.icon-item p {margin-top: 10px;text-align: center;
}.icon-mark {color: #2db7f5;
}
如下是进行检索的结果:
demo 实现说明
使用create-react-app
创建项目:
create-react-app --template typescript react-search-web
引入antd
做为UI
框架,为了与项目中antd
版本保持一致,这里我们使用3.26.18
版本的antd
:
yarn add antd@3.26.18
如下是生成的项目目录结构:
模糊搜索
模糊搜索这里是使用includes
方法实现,检索现有icons
数据中包含search
值的内容,如下代码所示:
icons.filter(type => type.includes(search))
结果高亮
对于检索结果进行高亮显示,主要是通过search
值构建正则对iconType
进行分割,将与search
值一致的内容进行color: #2db7f5
高亮,代码如下:
const renderIconType = (iconType: string, search: string) => {if (!search) return iconType;const reg = new RegExp(search, 'ig');const splitIconTypes = iconType.split(reg);const matchIconTypes = iconType.match(reg) as Array<string>;return (<React.Fragment>{matchIconTypes.map((_, index) => {return (<React.Fragment key={ index }><span>{ splitIconTypes[index] }</span><span className="icon-mark">{ matchIconTypes[index] }</span></React.Fragment>)})}<span>{ splitIconTypes[splitIconTypes.length - 1] || '' }</span></React.Fragment>)};
不可不知的react模糊搜索与结果高亮相关推荐
- 你不可不知道的React生命周期
点小蓝字加关注! 作者:kim 来源:原创 写在前面 咱今天聊的话题是React生命周期,灵感来自于最近在网上发现一篇关于react生命周期的文章,里面记录的知识点竟然与小编所get到的有出入.作为一 ...
- sublime67linter-php,Sublime Text 3 搭建 React.js 开发环境
Sublime有很强的自定义功能,插件库很庞大,针对新语言插件更新很快,配合使用可以快速搭建适配语言的开发环境. 支持ES6, React.js, jsx代码高亮,对 JavaScript, jQue ...
- sublime text3搭建react native
Sublime Text 3 搭建React.js开发环境 Sublime有很强的自定义功能,插件库很庞大,针对新语言插件更新很快,配合使用可以快速搭建适配语言的开发环境. 1. babel-subl ...
- 单文件快速体验使用react输出hello_world
看了下react官方的hello world教程, 感觉对新手很不友好.codepen虽然好用, 但是封装太多东西, 看起来 太抽象. 还是喜欢像学习jQuery那样, 直接在单文件中引入必要的js文 ...
- Sublime Text 3 搭建 React.js 开发环境
Sublime有很强的自定义功能,插件库很庞大,针对新语言插件更新很快,配合使用可以快速搭建适配语言的开发环境. 1. babel-sublime 支持ES6, React.js, jsx代码高亮,对 ...
- React+Webpack快速上手指南
2019独角兽企业重金招聘Python工程师标准>>> 前言 这篇文章不是有关React和Webpack的教程,只是一篇能够让你快速上手使用目前这两种热门技术的前端指南,并假设你对两 ...
- React 源码剖析系列 - 不可思议的 react diff
目前,前端领域中 React 势头正盛,使用者众多却少有能够深入剖析内部实现机制和原理.本系列文章希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. React diff 作 ...
- Comi - 小程序 markdown 渲染和代码高亮解决方案
写在前面 Comi 读 ['kəʊmɪ],类似中文 科米,是腾讯 Omi 团队开发的小程序代码高亮和 markdown 渲染组件.有了这个组件加持,小程序技术社区可以开始搞起来了. 体验 感谢[小程序 ...
- c++ websocket客户端_你要的websocket都在这,收好不谢~~~
此号已经沉寂多时,似乎已经忘了上一次更新是什么时候了!这一次重拾旧爱,希望能够一直保持下去,坚持写作,快乐你我他 今天的主题是websocket,相信搞研发的兄弟对websocket并不陌生,都202 ...
最新文章
- Django 分页和使用Ajax5.3
- 飞机大战html游戏全代码js、jquery操作
- ASP.NET 调味品:AJAX
- 【数字信号处理】序列傅里叶变换 ( 基本序列的傅里叶变换 | e^jωn 的傅里叶变换 )
- IntelliJ IDEA 常用设置
- C++常用方法笔记资料
- [TODO]com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method
- html与js二级菜单横排,JavaScript实现横向滑出的多级菜单效果
- 微信小程序开发学习笔记002--微信小程序框架解密
- 计算机兴趣小组活动教学教案,长春一中计算机兴趣小组教案.ppt
- python创建txt文件并写入-python如何将数据写入本地txt文本文件
- 【QT学习】搭建环境+hello world
- H12-211数通HCNA题库解析(一)
- [PTA]7-116 计算圆周率(c语言)(学习记录)
- 我用python做期货_使用Python计算股票期货,量化程序化交易
- mariadb审计插件
- vue项目的IE兼容问题
- php生成小程序二维码出现40001的情况
- matlab等式操作,matlab处理一个等式方程,急用,谢谢
- 工信部就垃圾短信问题约谈7家虚拟运营商