![](/img/trans.png)
[英]Element.focus() doesn't work when called within a function handler for addEventListener()
[英]element.focus() doesn't work on rerendered contentEditable div element
import React, { useEffect, useState } from "react";
import "./styles.css";
const RichText = () => {
const [value, setValue] = useState("");
useEffect(() => {
const div = document.getElementById("textarea");
if (div) {
setTimeout(() => {
div.focus();
}, 0);
}
});
return (
<div
className="rich-text"
onInput={(e) => {
setValue(e.target.innerText);
}}
contentEditable
id="textarea"
dangerouslySetInnerHTML={{
__html: value
}}
/>
);
};
export default RichText;
我想實現富文本組件,想法是您可以在某個字段內輸入文本,您可以設置該文本的樣式(使其變為粗體、斜體、下划線等)。 我想在value
state 變量上使用相同的文本值,然后以某種方式將其包裝在 html 標簽<p>Hello <b> Andrew</b></p>
內,並在同一字段中實時顯示,樣式. 為了在div
、 contentEditable
字段中顯示html
標簽,我需要使用dangerouslySetInnerHTML
,這是主要問題。 每次按下按鈕時,我都會更新值,然后重新渲染組件,焦點位於字段的開頭,但我希望它在您輸入新文本時位於末尾。 我試圖通過ref
=> ref.current.focus()
來實現它,它不起作用,在上面的代碼中你可以看到我也嘗試通過 vanilla js 使用超時來實現它,它也沒有work, autoFocus
- 只能用於input, textarea, etc
,div 可以與此屬性一起使用。 我已將其保存到ref
,但隨后我無法在div
內顯示包裝的 html 。 嘗試了很多案例,但它似乎是。 任何想法如何制作它?
問題是當使用useState
鈎子與contentEditable
和dangerouslySetInnerHTML
來同步值時。 當您在 div 中鍵入某些內容時,它會再次重新呈現並將 cursor 重新啟動。
您可以使用useRef
組件中的實例變量(使用引用更新值)來解決此問題。
您應該使用innerHTML
而不是innerText
來保存 HTML 字符串
嘗試如下
import React, { useRef } from "react";
import "./styles.css";
const RichText = () => {
const editableRef = useRef(null);
const { current: value } = useRef(
'<div style="color:green">my initial content</div>'
);
const setValue = (e) => {
value.current = e.target.innerHTML;
};
const keepFocus = () => {
const { current } = editableRef;
if (current) {
current.focus();
}
};
return (
<div
className="rich-text"
onInput={setValue}
contentEditable
id="textarea"
ref={editableRef}
onBlur={keepFocus}
dangerouslySetInnerHTML={{
__html: value
}}
/>
);
};
export default RichText;
import React from "react";
import "./styles.css";
class TextInput extends React.Component {
constructor(props) {
super();
this.state = { value: "" };
}
shouldComponentUpdate() {
return true;
}
componentDidUpdate() {
const el = document.getElementById("textarea");
if (el) {
console.log(el.selectionStart, el.selectionEnd);
var range, selection;
if (document.createRange) {
//Firefox, Chrome, Opera, Safari, IE 9+
range = document.createRange(); //Create a range (a range is a like the selection but invisible)
range.selectNodeContents(el); //Select the entire contents of the element with the range
range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start
selection = window.getSelection(); //get the selection object (allows you to change selection)
selection.removeAllRanges(); //remove any selections already made
selection.addRange(range); //make the range you have just created the visible selection
} else if (document.selection) {
//IE 8 and lower
range = document.body.createTextRange(); //Create a range (a range is a like the selection but invisible)
range.moveToElementText(el); //Select the entire contents of the element with the range
range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start
range.select(); //Select the range (make it the visible selection
}
}
}
update(value) {
this.setState({ value });
}
render() {
console.log(this.state.value);
return (
<div
className="rich-text"
onInput={(e) => {
this.update(e.target.innerText);
}}
contentEditable
id="textarea"
dangerouslySetInnerHTML={{
__html: `<b>${this.state.value}</b>`
}}
/>
);
}
}
export default TextInput;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.