monaco-editor 组件化操作

import * as monaco from 'monaco-editor';
import React, { useCallback, useEffect, useRef } from 'react';

interface IProps {
  /** 编辑器内容 */
  value?: string;
  /** 编辑器语言,默认 json */
  language?: string;
  /** 是否只读 */
  readOnly?: boolean;
}

const MonacoWeb: React.FC<IProps> = ({
  value = '',
  language = 'json',
  readOnly = false,
}) => {
  const domRef = useRef<HTMLDivElement>(null);
  const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();

  // 根据 Monaco 计算的 contentHeight 调整容器高度
  const updateHeight = useCallback(() => {
    const editor = editorRef.current;
    if (!editor || !domRef.current) return;
    const contentHeight = editor.getContentHeight();
    domRef.current.style.height = `${contentHeight}px`;
    editor.layout();
  }, []);

  const createEditor = useCallback(() => {
    if (!domRef.current) return;
    try {
      editorRef.current = monaco.editor.create(domRef.current, {
        value,
        language,
        minimap: { enabled: false },
        automaticLayout: true,
        codeLens: true,
        colorDecorators: true,
        contextmenu: false,
        readOnly,
        formatOnPaste: true,
        overviewRulerBorder: false,
        scrollBeyondLastLine: false,
        scrollbar: { vertical: 'hidden', horizontal: 'auto', handleMouseWheel: false },
        theme: 'vs',
        fontSize: 12,
        lineNumbers: 'off', // 关闭行号
        wordWrap: 'on', // 开启换行
      });

      // 内容尺寸变化时重新调整高度(内容变化 / 宽度变化导致换行重排都会触发)
      editorRef.current.onDidContentSizeChange(() => {
        updateHeight();
      });

      // 初始加载时立即计算高度
      updateHeight();
    } catch (error) {
      console.error('Monaco editor creation failed:', error);
    }
  }, []);

  // 初始化编辑器
  useEffect(() => {
    createEditor();
    return () => {
      editorRef.current?.dispose();
      editorRef.current = undefined;
    };
  }, [createEditor]);

  // 同步 value
  useEffect(() => {
    if (!editorRef.current) return;
    const model = editorRef.current.getModel();
    if (model && value !== model.getValue()) {
      editorRef.current.setValue(value);
    }
  }, [value]);

  // 同步 language
  useEffect(() => {
    if (!editorRef.current) return;
    const model = editorRef.current.getModel();
    if (model) {
      monaco.editor.setModelLanguage(model, language);
    }
  }, [language]);

  // 同步 readOnly
  useEffect(() => {
    editorRef.current?.updateOptions({ readOnly });
  }, [readOnly]);

  return (
    <div
      ref={domRef}
      style={{
        width: '100%',
      }}
    />
  );
};

export default MonacoWeb;

import MonacoWeb from '@/components/monacoWeb';

<MonacoWeb
        value={JSON.stringify(jsonValue?.data, null, 2)}
        language="json"
        readOnly
      />

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容