页面编辑器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)
   }}
 />
相关推荐
excel几秒前
JS 函数终极指南:this、闭包、递归、尾调用、柯里化,一次性吃透
前端
夏天想1 分钟前
html模拟websocket通信
前端
阿珊和她的猫4 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
加班是不可能的,除非双倍日工资9 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi9 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip10 小时前
vite和webpack打包结构控制
前端·javascript
excel10 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国10 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼10 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy10 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程