如何使用 React 根据用户输入突出显示文本?

How to highlight text based on user input with React?

让我们以可编辑 <div>contenteditable="true":

的准系统为例
<div contenteditable="true">
  Edit this 
</div>

用户能够input/edit/delete这个<div>元素的内容。

对于某些输入形式,如果用户输入的文本大于某个字符限制,则添加超过此限制的字符将突出显示(警告用户停止添加文本)。

我怎样才能用 React 实现这样的目标?

我认为 <span> 可用于突出显示文本,但我无法概念化在达到字符数限制后如何开始突出显示。

如果问题清楚,请告诉我。谢谢你的帮助。

您可以通过检查 onchange 事件来达到 div 文本长度 并用一个 span 包装额外的文本,并通过连接文本(没有额外的字符)+ 包装的额外文本 span;

再次设置 div 的内部 html

(由于 xss 注入,不建议使用 innerHTML,但这是我找到的解决此问题的唯一方法)

这里的主要问题是设置 div innerHTML 后,您的光标将停留在 div 文本的开头,所以我做了一个小技巧来在文本末尾设置选择使用

       // get textt par before extra text
      let start =  html.slice(0, MAX_LENGTH ) ;
      // get extra text
      let overflow =  html.slice(MAX_LENGTH) ;
      // rap extra text by span
      overflow = `<span style="color:${COLOR}">${overflow}</span>`;
      //set text as innerHTML (or use dangerouslyINerHTML with sate var)
      ref.current.innerHTML = start+overflow
      
      // below part is to set cursor , at the end after inner html 
      // because innerHTML will reset selection to the start of div text
      let range = document.createRange()
      var sel = window.getSelection()
      range.setStart(ref.current.lastChild, 1   )

      sel.removeAllRanges()
      sel.addRange(range)

请参阅此处使用不同道具示例创建组件并使用不同道具的工作 snnipet

const { useRef } = React;

/* create Eitable Component */
const EditAbleDiv  =( props ) => {
  // get max length from props
  const MAX_LENGTH = props.maxLength || 40;
  // get color from props
  const COLOR = props.warningColor || 'orange';
  
  let ref = useRef(null);
  
  
  // on change event
  const contentChange = (e) => {
    
    // get only text without html tags
    let html = e.target.innerText;
    
    if (html.length > MAX_LENGTH) {

      // get textt par before extra text
      let start =  html.slice(0, MAX_LENGTH ) ;
      // get extra text
      let overflow =  html.slice(MAX_LENGTH) ;
      // rap extra text by span
      overflow = `<span style="color:${COLOR}">${overflow}</span>`;
      //set text as innerHTML (or use dangerouslyINerHTML with sate var)
      ref.current.innerHTML = start+overflow
      
      // below part is to set cursor , at the end after inner html 
      // because innerHTML will reset selection to the start of div text
      let range = document.createRange()
      var sel = window.getSelection()
      range.setStart(ref.current.lastChild, 1   )

      sel.removeAllRanges()
      sel.addRange(range)

    }
  }

  return <div  ref={ref}
  contentEditable 
  onInput={contentChange} 
  >
    Edit text
</div>
}
/* end component */


function App() {
  
  return (
    <div>
      <b> click in below div to edit text </b> <br/><br/>
      <EditAbleDiv maxLength={25} />
      <hr />
      <EditAbleDiv maxLength={18} warningColor={"red"} />
      <hr />
      <EditAbleDiv maxLength={12} warningColor={"green"} />
    </div>
  )
}

ReactDOM.render(
    <App />,
    document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>