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

显示效果:

初始化页面时:

2cacd40d3968477585d8674b3ff964db.png

2s后(模拟异步请求数据)显示:

73bd463cfc634e0f894bd4114ae05331.png

代码仓库地址:

命运推手/my_web

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值