You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 03:45:04