React实现模糊搜索和关键字高亮

模糊搜索与关键词点亮

背景

公司需要一个可视化页面,作为Redis查询展示的工具,方便同事进行快速检索。

要求将后端返回的报文,完整展现在识图中,并且可以提供关键词检索和关键词点亮的功能,以便快速定位关键词。

整体效果预览:

主要功能

  1. 点击搜索:返回的大字符串形式报文被组装成JSON的格式,点击搜索匹配相应字段, 并高亮显示
  2. 点击区分大小写:模糊匹配 OR 精确匹配
  3. 查找下一个:被选中的字段,往下移动一个,下一个的背景颜色切换为另一高亮色

解决

  1. 匹配到的文本,动态插入样式
  2. 使用正则解决匹配问题
  3. 点击下一个时,动态切换类名和背景色

代码实现

仅仅贴出主要代码

DOM

jsx 复制代码
...
<Input 
    value={this.state.txt}
    placeholder="请输入检索内容"
    onChange={e => this.setState({txt: e.target.value})}
></Input>
<Button onClick={this.dispatchHighLightText}>
    搜索
</Button>
...
<CheckBos 
    checked={this.state.isCheck}
    onChange={e => this.setState({isCheck: e.target.checked})}
>
	区分大小写
</CheckBos>
...
<Button
    onClick={this.searchToNext}
>
    查找下一个
</Button>

...
<pre
    dangerouslySetInnerHTML={{__html: this.state.information}}
    contentEditable
>
    {/*动态插入html的容器*/}
</pre>

CSS

less 复制代码
// 每个匹配到的都有的类名
.highLight{
    background-color: #a9a9a9;
}
// 点击下一个时的类名,默认为第一个
.current{
    background-color: #32aaf8;
}

JS

  • 点击搜索时
jsx 复制代码
colorIndex = 0; // 初始化高亮标记
_information = ''; // 文本备份
dispatchHighLightText = () => {
    const {txt} = this.state; // 检索内容
    if(!txt){
        message.warning("请先输入查询条件"); 
        return;
    }
    // 重置高亮标记
    colorIndex = 0;
    const regex = new RegExp(txt, this.state.isCheck ? 'g' : 'gi'); // 不勾选 => 模糊匹配
    // 由于每次插入样式都会污染文本,所以每次都需要从备份文本中重新渲染
    const newInformation = _information;
    const hightLightTxt = newInformation.replace(regex, (match,index) => `<span class="highLight"> ${match} </span>`);
    this.setState({infomation: hightLightTxt}, () => {
        // 视图更新渲染然后,获取到dom
        let highLightEle = document.querySelectorAll('.highLight');
        this.updateHeight(highLightEle)
    }); // render
}

// 点亮目标关键字
updateHeight = (highLightEle) => {
    highLightEle.forEach((element, index) => {
        if(index === colorIndex){
            element.classList.add('current');
            element.scrollIntoView({ behavior: 'smooth', block: 'center'});
        }else{
            element.classList.remove('current');
        }
    })
}
  • 点击 "下一个"
jsx 复制代码
searchToNext = () => {
    let highLightEle = document.querySelectorAll('.highLight');
    if(heighLightEle.length){
        colrIndex = (colorIndex + 1 + highLightEle.length) % highLightEle.length;
        this.updateHeight(highLightEle)
    }
}

反思

  1. 本来想用偏移量window.getSelection 和 document.createRange 以及相关api模拟富文本实现光标跳转定位的,可是发现偏移量不好确定(小菜鸡)
  2. 每次渲染的时候需要拿新的备份的文本进行替换,不要用脏数据
  3. pre标签可以很好的保留文本原来的样式,不能用textarea
  4. dangerouslySetInnerHTML接收的是一个对象

仅以本文作为工作记录

相关推荐
前端开发爱好者17 分钟前
Vue3 超强“积木”组件!5 分钟搞定可交互 3D 机房蓝图!
前端·javascript·vue.js
前端开发爱好者21 分钟前
尤雨溪力荐!Vue3 专属!100+ 动效组件!
前端·javascript·vue.js
前端开发爱好者22 分钟前
尤雨溪力荐!Vue3 生态最强大的 14 个 UI 组件库!
前端·javascript·vue.js
lb291736 分钟前
关于多个el-input的自动聚焦,每输入完一个el-input,自动聚焦到下一个
前端·javascript·vue.js
lingliang39 分钟前
使用 JS 渲染页面并导出为PDF 常见问题与修复
javascript·pdf·vue
sorryhc1 小时前
【AI解读源码系列】ant design mobile——Divider分割线
前端·javascript·react.js
前端进阶者1 小时前
electron-vite_20配置依赖包运行时区外部加载commonjsExternals_vite-plugin-commonjs-externals
前端·electron
anyup1 小时前
🔥 uView Pro 全新升级来啦!一行配置,解锁 uView Pro 全局 TS 类型提示与校验
前端·vue.js·uni-app
Jimmy1 小时前
使用 Electron 在 5 分钟内创建一个桌面的 React 应用
前端·javascript·electron
玲小珑1 小时前
LangChain.js 完全开发手册(二)Prompt Engineering 与模板系统深度实践
前端·langchain·ai编程