React JS实现文本指定词加粗高亮 点击按钮无响应问题
问题根因
你的代码没有生效是三个核心错误导致的:
- 违背React状态驱动的核心逻辑:你全程通过
document.getElementById直接操作DOM,既没有把处理后的内容存到组件状态中,也没有把处理结果嵌入JSX参与渲染,页面自然不会有任何变化。 - 对
react-string-replace的用法完全错误:这个库是纯函数,执行后不会修改传入的原始参数,只会返回处理完成的React节点数组;你两次调用都没有接收返回值,且第二版代码直接传入DOM元素对象作为第一个参数(该库要求第一个参数必须是纯字符串或者React节点数组),库根本无法正常执行匹配逻辑。 - 渲染容器错误:你试图把带
<span>标签的富文本内容放到<textarea>里渲染,textarea是原生表单控件,内部只能展示纯文本,完全不支持嵌套HTML标签,就算你把内容塞进去也不可能显示加粗效果。
修复方案
直接用React状态管理所有可变数据,移除所有手动DOM操作,区分纯文本编辑区和富文本预览区,处理后的高亮内容直接在JSX中渲染即可。
完整可运行代码如下:
import React, { useState } from 'react' import "./Blog.css" import reactStringReplace from 'react-string-replace'; // 正则特殊字符转义工具 const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); export default function Blog() { const [titleText, setTitText] = useState("Enter Title here...."); const [desText, setDesText] = useState("Enter Text here...."); // 存储触发高亮的关键词 const [searchKeyword, setSearchKeyword] = useState(""); // 存储搜索框实时输入值 const [searchInput, setSearchInput] = useState(""); // 点击按钮触发高亮 const handleSearch = () => { setSearchKeyword(searchInput.trim()); } const handleOnChangetit = (event) => { setTitText(event.target.value); } const handleOnChangedes = (event) => { setDesText(event.target.value); } const handleSearchInputChange = (e) => { setSearchInput(e.target.value); } // 生成高亮后的正文内容 const renderHighlightedText = () => { if (!searchKeyword) return desText; const pattern = new RegExp(escapeRegExp(searchKeyword), "gi"); return reactStringReplace(desText, pattern, (match, i) => ( <span key={i} style={{ fontWeight: 'bold' }}>{match}</span> )) } // 生成高亮后的标题内容 const renderHighlightedTitle = () => { if (!searchKeyword) return titleText; const pattern = new RegExp(escapeRegExp(searchKeyword), "gi"); return reactStringReplace(titleText, pattern, (match, i) => ( <span key={i} style={{ fontWeight: 'bold' }}>{match}</span> )) } return ( <> <div className="blogButtons"> <input className="searchbar" type="search" value={searchInput} onChange={handleSearchInputChange} placeholder="Search" aria-label="Search..." /> <button className="btn btn-outline-success" onClick={handleSearch} type="button"> <i className="fa-solid fa-magnifying-glass"> Bold Text</i> </button> </div> <div className="textbox"> {/* 纯文本编辑区 */} <textarea type="text" value={titleText} onChange={handleOnChangetit} className='blogtitle' /> <textarea type="text" value={desText} onChange={handleOnChangedes} className='blogarea' /> {/* 高亮预览区 */} <div className="blog-preview-title">{renderHighlightedTitle()}</div> <div className="blog-preview-content" id="blog-text">{renderHighlightedText()}</div> </div> </> ) }
关键修改说明
- 所有可变内容全部通过React state管理,数据修改统一走
setState触发视图更新,完全移除手动DOM操作逻辑,从根源上避免“处理了内容但页面不刷新”的问题。 - 修正
react-string-replace调用方式:传入纯文本作为匹配源,接收函数返回的React节点数组直接参与渲染。 - 区分编辑区和预览区:textarea仅负责纯文本输入,普通div负责渲染带加粗样式的富文本内容,解决容器不支持HTML标签的问题。如果不需要单独编辑区,直接删除两个textarea标签即可。
- 按钮type改为
button,避免默认submit行为触发非预期的页面刷新。 - 搜索框改为受控组件,输入内容实时同步到state,不用点击时再去DOM节点中取值,逻辑更稳定。
内容的提问来源于stack exchange,提问作者Pratyush Patra
相关产品推荐
相关产品推荐

