页面编辑器CodeMirror初始化不显示行号或文本内容

延迟刷新

本来想延迟100毫秒的,但是会出现样式向左偏移的情况,于是试了试500毫秒,发现就没有问题了,可能是样式什么是需要一个加载过程吧。

javascript 复制代码
  useEffect(() => {
    editorRef.current?.setValue(value || '');
    setTimeout(() => {
      editorRef.current?.refresh();
    }, 500);
  }, [value]);

另外记录一下写的编辑器组件

npm install codemirror --save

javascript 复制代码
import CodeMirror, { EditorFromTextArea } from 'codemirror';
import 'codemirror/lib/codemirror.css';
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';

// 导入需要的语言模式和样式主题
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/hint/javascript-hint.js'; // 自动提示
import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/xml/xml';
import 'codemirror/theme/material.css'; // 加载的样式主题 https://codemirror.net/5/theme/

// 折叠代码块
import 'codemirror/addon/fold/brace-fold.js';
import 'codemirror/addon/fold/comment-fold.js';
import 'codemirror/addon/fold/foldcode.js';
import 'codemirror/addon/fold/foldgutter.js';

import 'codemirror/addon/selection/active-line.js'; // 当前行高亮

import 'codemirror/addon/hint/anyword-hint.js'; // end
import 'codemirror/addon/hint/show-hint.css'; // start-ctrl+空格代码提示补全
import 'codemirror/addon/hint/show-hint.js';

// 定义组件属性类型
interface CodeMirrorEditorProps {
  ref: any;
  readOnly: boolean;
  value: string;
  language: string;
  theme?: 'default' | 'material';
  height?: number;
  width?: number;
  onChange: (value: string) => void;
  onShiftEnter?: () => void;
  onBlur?: (value: string) => void;
  onChangeLine?: () => void;
}

const CodeMirrorEditor: React.FC<CodeMirrorEditorProps> = forwardRef((props, ref) => {
  const { language, readOnly, value, theme, width, height } = props;
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const editorRef = useRef<EditorFromTextArea>();

  useImperativeHandle(ref, () => ({
    refresh: () => {
      editorRef.current?.refresh();
    },
  }));

  /** 失焦 */
  const blur = (instance: any) => {
    if (props.onBlur) {
      props.onBlur(instance.doc.getValue());
    }
  };

  /** 键盘按键按下 */
  const keydown = (_: any, change: any) => {
    if (change.shiftKey === true && change.keyCode === 13) {
      if (props.onShiftEnter) {
        props.onShiftEnter();
      }
      change.preventDefault();
    }
  };

  /** 编辑内容变化 */
  const codemirrorValueChange = (doc: any, change: any) => {
    doc.eachLine((line: any) => {
      if (line.text.startsWith('//') || line.text.startsWith('#')) {
        doc.addLineClass(line, 'wrap', 'notes');
      } else if (line.wrapClass === 'notes') {
        doc.removeLineClass(line, 'wrap', 'notes');
      }
    });

    if (change.origin !== 'setValue') {
      if (props.onChange) {
        props.onChange(doc.getValue());
      }
    }
  };

  const initCodeMirror = () => {
    const editorConfig = {
      readOnly: readOnly,
      tabSize: 4, // 制表符的宽度。默认为 4。
      fontSize: '16px', // 字体大小
      styleActiveLine: !readOnly, // 选中行高亮
      autoCloseBrackets: true, // 在键入时自动关闭括号和引号
      showCursorWhenSelecting: true, // 当选择处于活动状态时是否应绘制光标。默认为 false。这里设置成自动补全
      lineWrapping: true, // ,CodeMirror 是否应该滚动或换行。默认为false(滚动)。这里设置成换行
      lineNumbers: true, // 是否在编辑器左侧显示行号
      firstLineNumber: 1,
      fullScreen: true, //当设置为 时true,将使编辑器全屏显示(如占据整个浏览器窗口)。
      mode: language, // 使用模式
      // theme: 'default' // 编辑器样式的主题 必须确保.cm-s-[name] 加载定义相应样式的 CSS 文件。默认值为"default",颜色包含在 中codemirror.css。可以一次使用多个主题类,例如将和类"foo bar"都分配给编辑器。cm-s-foocm-s-bar
      theme: theme || 'default', // 编辑器样式的主题 必须确保.cm-s-[name] 加载定义相应样式的 CSS 文件。默认值为"default",颜色包含在 中codemirror.css。可以一次使用多个主题类,例如将和类"foo bar"都分配给编辑器。cm-s-foocm-s-bar
      foldGutter: true,
      gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
      extraKeys: { Ctrl: 'autocomplete' },
    };

    editorRef.current = CodeMirror.fromTextArea(textareaRef.current!, editorConfig);

    // 监听编辑器内容变化事件
    editorRef.current.on('change', codemirrorValueChange);
    editorRef.current.on('keydown', keydown);
    editorRef.current.on('blur', blur);

    // const { value, width, height } = props;
    editorRef.current.setValue(value || '');
    if (width || height) {
      editorRef.current.setSize(width, height);
    }
  };

  useEffect(() => {
    if (textareaRef.current) {
      initCodeMirror();
    }

    return () => {
      // 清理和销毁编辑器实例
      editorRef.current?.toTextArea();
    };
  }, [readOnly, textareaRef, theme, width, height, language]);

  useEffect(() => {
    editorRef.current?.setValue(value || '');
    setTimeout(() => {
      editorRef.current?.refresh();
    }, 500);
  }, [value]);

  return <textarea ref={textareaRef} />;
});

export default CodeMirrorEditor;

使用

javascript 复制代码
import { CodeMirrorEditor } from '@/components';
<CodeMirrorEditor
     height={550}
     theme={'default'}
     readOnly={false}
     value={content || ''}
     language="javascript"
     onChange={(value) => {
       console.log('值',value)
   }}
 />
相关推荐
恋猫de小郭29 分钟前
Android Studio Cloud 正式上线,不只是 Android,随时随地改 bug
android·前端·flutter
清岚_lxn5 小时前
原生SSE实现AI智能问答+Vue3前端打字机流效果
前端·javascript·人工智能·vue·ai问答
ZoeLandia5 小时前
Element UI 设置 el-table-column 宽度 width 为百分比无效
前端·ui·element-ui
橘子味的冰淇淋~6 小时前
解决 vite.config.ts 引入scss 预处理报错
前端·vue·scss
小小小小宇8 小时前
V8 引擎垃圾回收机制详解
前端
lauo8 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
拉不动的猪8 小时前
设计模式之------单例模式
前端·javascript·面试
一袋米扛几楼989 小时前
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
前端·react.js·前端框架
Alt.99 小时前
SpringMVC基础二(RestFul、接收数据、视图跳转)
java·开发语言·前端·mvc
进取星辰9 小时前
1、从零搭建魔法工坊:React 19 新手村生存指南
前端·react.js·前端框架