React写关键字高亮的三个方案
1.js正则replaceAll+dangerouslySetInnerHTML={{ __html: xxx }}危险属性
步骤最简单,但是是危险属性,不推荐使用,项目中实在没有头绪,可以使用它应急
通过useMemo计算得到新的状态值,赋值给dangerouslySetInnerHTML属性的__html
关键代码:
const [state1, setState1] = useState('我爱中国,中国爱我')
const updateState1 = useMemo(() => {
return state1.replaceAll('中国', '<span style="color:red;">中国</span>')
}, [state1])
<div dangerouslySetInnerHTML={{ __html: updateState1 }}></div>
2.useMemo计算遍历后将关键字替换为React标签写法(内容为关键字),使用_.map渲染
(要不是replace不能转换为React标签,只支持字符串也不用这么麻烦)
关键代码:
const updateState2 = useMemo(() => {
return highlightPassword(state2, '_.map_')
}, [state2])
function highlightPassword(str0: any, key_prefix?: string) {
const password = '中国';
const pattern = new RegExp(`\\B(?=((${password})+)+(?!(${password})))`, 'g')
return str0.replace(pattern, '||||').split('||||').map((item, index) => {
const idx = item.indexOf(password)
return <span key={key_prefix + index}>
{
idx >= 0
? <><span style={{ color: 'red' }}>{item.substring(0, password.length)}</span>{item.substring(password.length, item.length)}</>
: item
}
</span>
});
}
<p>map遍历children元素:</p>
{_.map(updateState2, (child) => {
return child
})}
3.遍历后将关键字替换为React标签写法(内容为关键字),使用ReactDOM.render方法插入到指定元素中
关键代码:
const Test = () => {
const [state2, setState2] = useState<any>('我爱中国,中国中国爱我')
useEffect(() => {
// 遍历将关键字换成react写法的标签,使用ReactDOM.render方法渲染到页面上
const str = highlightPassword(state2, 'ReactDOM.render_')
ReactDOM.render(<div>{str}</div>, document.getElementsByClassName('my-highlight-test')[0])
}, [state2])
function highlightPassword(str0: any, key_prefix?: string) {
const password = '中国';
const pattern = new RegExp(`\\B(?=((${password})+)+(?!(${password})))`, 'g')
return str0.replace(pattern, '||||').split('||||').map((item, index) => {
const idx = item.indexOf(password)
return <span key={key_prefix + index}>
{
idx >= 0
? <><span style={{ color: 'red' }}>{item.substring(0, password.length)}</span>{item.substring(password.length, item.length)}</>
: item
}
</span>
});
}
<p>ReactDOM.render方法:</p>
<div className="my-highlight-test"></div>
完整代码示例:
import React, { useEffect, useMemo, useState } from 'react'
import ReactDOM from 'react-dom';
import _ from 'lodash';
const Test = () => {
const [password,] = useState('中国')
const [state1, setState1] = useState('我爱中国,中国爱我')
const [state2, setState2] = useState<any>('我爱中国,中国中国爱我')
useEffect(() => {
// 遍历将关键字换成react写法的标签,使用ReactDOM.render方法渲染到页面上
const str = highlightPassword(state2, 'ReactDOM.render_')
ReactDOM.render(<div>{str}</div>, document.getElementsByClassName('my-highlight-test')[0])
}, [state2])
const updateState1 = useMemo(() => {
return state1.replaceAll(password, str => `<span style="color:red;">${str}</span>`)
}, [state1])
const updateState2 = useMemo(() => {
return highlightPassword(state2, '_.map_')
}, [state2])
useEffect(() => {
setTimeout(() => {
setState1('哈哈哈,中国万岁,万岁万万岁,中国加油!')
setState2('哈哈哈,中国中国万岁,万岁万万岁,中国中国加油!爱你中国!')
}, 2000)
}, [])
function highlightPassword(str0: any, key_prefix?: string) {
const pattern = new RegExp(`\\B(?=((${password})+)+(?!(${password})))`, 'g')
return str0.replace(pattern, '||||').split('||||').map((item, index) => {
const idx = item.indexOf(password)
return <span key={key_prefix + index}>
{
idx >= 0
? <><span style={{ color: 'red' }}>{item.substring(0, password.length)}</span>{item.substring(password.length, item.length)}</>
: item
}
</span>
});
}
return (
<div>
<p>dangerouslySetInnerHTML方式:</p>
<div dangerouslySetInnerHTML={{ __html: updateState1 }}></div>
<p>map遍历children元素:</p>
{_.map(updateState2, (child) => {
return child
})}
<p>ReactDOM.render方法:</p>
<div className="my-highlight-test"></div>
</div>
)
}
export default Test
显示效果:
初始化页面时:
2s后(模拟异步请求数据)显示:
代码仓库地址:
命运推手/my_web