应用场景
已知开源社区已经有react封装的富文本组件,一般的文本编辑需求足够满足,但是当有特殊需求无法满足时,可能需要用到非react封装的富文本组件。
当使用非react封装的富文本编辑器时,react组件内的state与编辑器的内容交换有点小毛病,本经验给出解决思路。
实施过程
这里以代码编辑组件"ace"为例。
npm i ace-builds
定义编辑器的容器
<div ref={setDom_editor_main}/>
const [dom_editor_main, setDom_editor_main] = useState<HTMLElement | null>()
定义内容交换的state
const [content,setContent]=useState('')
const [codeEditor, setCodeEditor] = useState<ace.Ace.Editor>()
function handleEditorValueChange() {
if (codeEditor) {
const val = codeEditor.getValue()
if (content!== val) {
setContent(val)
}
}
}
初始化编辑器
const otherState = useRef({
isInit: true//标识页面首次载入
})
useEffect(() => {//赋值给编辑器
if (otherState.current.isInit && codeEditor) {
codeEditor?.off('change', handleEditorValueChange)
codeEditor?.on('change', handleEditorValueChange)//绑定事件
codeEditor.setValue(content)
otherState.current.isInit = false
}
}, [codeEditor, content])
//编辑器初始化
useEffect(() => {
if (!dom_editor_main) {
return
}
const editor = ace.edit(dom_editor_main)
editor.session.setMode('ace/mode/sql')
editor.setTheme('ace/theme/github')
editor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
showPrintMargin: false,
wrap: 120
})
setCodeEditor(editor)
}, [dom_editor_main])
useEffect(() => {
return () => {//销毁编辑器
codeEditor?.off('change', handleEditorValueChange)
codeEditor?.destroy()
}
}, [])
当页面有初始化加载数据时
async function loadData(id:string){
//示范从API读取数据
const data=await api_loadData(id)
//赋值给编辑器
setContent(data)
}
//假设你的组件接受id属性用来加载数据
useEffect(()=>{
if(props.id){
otherState.current.isInit = true
loadData(props.id)
}
},[props.id])
由于编辑器通过change事件传值给content,那么保存时可以直接取content或者调用编辑器的getValue