【问题标题】:How to highlight text based on user input with React?如何使用 React 根据用户输入突出显示文本?
【发布时间】:2021-05-25 10:35:47
【问题描述】:

让我们以<div>contenteditable="true" 的准系统编辑为例:

<div contenteditable="true">
  Edit this 
</div>

用户可以input/edit/delete这个&lt;div&gt;元素的内容。

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

我如何使用 React 实现这样的目标?

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

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

【问题讨论】:

    标签: javascript html reactjs jsx contenteditable


    【解决方案1】:

    您可以通过签入onchange 事件、div 文本长度来达到 并通过跨度包装额外的文本,并通过连接文本(没有额外的字符)再次设置该 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)
    

    参见此处使用不同道具的工作片段示例创建了一个组件并使用不同的道具

    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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      相关资源
      最近更新 更多