如何使用 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>
让我们以可编辑 <div>
和 contenteditable="true"
:
<div contenteditable="true">
Edit this
</div>
用户能够input/edit/delete
这个<div>
元素的内容。
对于某些输入形式,如果用户输入的文本大于某个字符限制,则添加超过此限制的字符将突出显示(警告用户停止添加文本)。
我怎样才能用 React 实现这样的目标?
我认为 <span>
可用于突出显示文本,但我无法概念化在达到字符数限制后如何开始突出显示。
如果问题清楚,请告诉我。谢谢你的帮助。
您可以通过检查 onchange
事件来达到 div 文本长度
并用一个 span 包装额外的文本,并通过连接文本(没有额外的字符)+ 包装的额外文本 span;
(由于 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>