如何在React函数式组件中正确集成使用Monaco Editor?
React函数式组件集成monaco-editor实现方案
1. 核心逻辑说明
你引入的Monaco对象已经包含了所有可用API,无需额外配置MonacoEnvironment(该对象仅用于自定义worker路径、全局默认配置等特殊场景,常规渲染无需调整),直接调用Monaco.editor.create挂载到真实DOM节点即可。
2. 完整代码修改示例
import { useRef, useEffect } from 'react'; import * as Monaco from 'monaco-editor/esm/vs/editor/editor.api'; // 保留你原有的其他依赖引入,比如Flex、Input等组件 function YourComponent(props) { const { value, onChange, error, readOnly, icon, handleKeyDown } = props; // 存储editor挂载的DOM容器 const editorContainerRef = useRef(null); // 存储editor实例,方便后续调用API const editorInstanceRef = useRef(null); useEffect(() => { // 确保容器存在且实例未初始化时才创建 if (!editorContainerRef.current || editorInstanceRef.current) return; // 初始化编辑器,和你要实现的原生create逻辑完全对齐 editorInstanceRef.current = Monaco.editor.create(editorContainerRef.current, { value: value || [ 'function x() {', '\tconsole.log("Hello world!");', '}' ].join('\n'), language: 'javascript', readOnly: readOnly, minimap: { enabled: false }, fontSize: 12, }); // 监听编辑器内容变化,同步到外层状态 const changeDisposable = editorInstanceRef.current.onDidChangeModelContent(() => { const currentValue = editorInstanceRef.current.getValue(); onChange?.(currentValue); }); // 监听键盘事件,对应你原有的onKeyPress逻辑 const keyDownDisposable = editorInstanceRef.current.onKeyDown((e) => { const currentValue = editorInstanceRef.current.getValue(); handleKeyDown?.(e, currentValue); }); // 组件销毁时销毁实例,释放内存避免泄漏 return () => { changeDisposable.dispose(); keyDownDisposable.dispose(); editorInstanceRef.current?.dispose(); editorInstanceRef.current = null; }; }, []); // 响应外部value变化,同步更新编辑器内容 useEffect(() => { if (!editorInstanceRef.current) return; const currentEditorValue = editorInstanceRef.current.getValue(); if (value !== currentEditorValue) { editorInstanceRef.current.setValue(value || ''); } }, [value]); // 响应readOnly属性变化 useEffect(() => { editorInstanceRef.current?.updateOptions({ readOnly }); }, [readOnly]); return ( <Flex> <Flex.Box auto> {/* 替换原有的Textarea为编辑器挂载容器,必须设置高度否则编辑器无法正常渲染 */} <div ref={editorContainerRef} style={{ height: '200px', border: error ? '1px solid #ff4d4f' : '1px solid #d9d9d9', borderRadius: '2px' }} /> </Flex.Box> <Flex align="flex-start" w="21px"> {icon} </Flex> </Flex> ); }
3. 功能测试常用API
你可以直接通过editorInstanceRef.current调用编辑器实例API完成测试:
- 获取当前编辑器内容:
editorInstanceRef.current.getValue() - 手动设置编辑器内容:
editorInstanceRef.current.setValue('自定义测试代码') - 切换语法高亮语言:
Monaco.editor.setModelLanguage(editorInstanceRef.current.getModel(), 'typescript') - 获取选中的代码片段:
editorInstanceRef.current.getModel().getValueInRange(editorInstanceRef.current.getSelection()) - 触发编辑器格式化:
editorInstanceRef.current.getAction('editor.action.formatDocument').run()
内容的提问来源于stack exchange,提问作者tRuEsAtM
相关产品推荐
相关产品推荐

