React+TypeScript项目中使用CodeMirror的步骤

 更新时间:2023年07月26日 11:37:53   作者:demo123567  
CodeMirror被广泛应用于许多Web应用程序和开发工具,之前做需求用到过codeMirror这个工具,觉得还不错,功能很强大,所以记录一下改工具的基础用法,对React+TypeScript项目中使用CodeMirror的步骤感兴趣的朋友跟随小编一起看看吧

前言

之前做需求用到过codeMirror这个工具,觉得还不错,功能很强大,所以记录一下改工具的基础用法,分享给大家。CodeMirror被广泛应用于许多Web应用程序和开发工具,例如代码编辑器、集成开发环境(IDE)、在线教育平台等。它提供了一个可嵌入的、灵活的解决方案,让开发者可以轻松地在网页中实现功能强大的代码编辑器。

使用codeMirror

步骤1:安装依赖

首先,你需要在React项目中安装CodeMirror及其相关依赖。可以使用以下命令进行安装:

npm install codemirror react-codemirror2 @types/codemirror

步骤2:导入所需模块、创建CodeMirror组件

import React, { useRef, useEffect } from 'react';
import CodeMirror, { EditorFromTextArea } from 'codemirror';
import 'codemirror/lib/codemirror.css';
// 导入需要的语言模式和样式主题
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/xml/xml';
import 'codemirror/mode/css/css';
import 'codemirror/mode/htmlmixed/htmlmixed';
import 'codemirror/theme/material.css';  // 加载的样式主题 https://codemirror.net/5/theme/
// 定义组件属性类型
interface CodeMirrorEditorProps {
  value: string;
  language: string;
  theme?: string;
  height?:Number;
  width?:Number;
  onChange: (value: string) => void;
  onShiftEnter?: () => void;
  onBlur?: (value: string) => void;
  onChangeLine?: () => void;
}
const CodeMirrorEditor: React.FC<CodeMirrorEditorProps> = (props) => {
  const { language } = props;
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const editorRef = useRef<EditorFromTextArea>();
  useEffect(() => {
    const textarea = textareaRef.current;
    if (!textarea) return;
    initCodeMirror();
    return () => {
      // 清理和销毁编辑器实例
      editorRef.current?.toTextArea();
    };
  }, []);
  const initCodeMirror = ()=>{
    const editorConfig = {
      tabSize: 2, // 制表符的宽度。默认为 4。
      fontSize: '16px', // 字体大小
      autoCloseBrackets: true, // 在键入时自动关闭括号和引号
      showCursorWhenSelecting: true, // 当选择处于活动状态时是否应绘制光标。默认为 false。这里设置成自动补全
      lineWrapping: true, // ,CodeMirror 是否应该滚动或换行。默认为false(滚动)。这里设置成换行
      lineNumbers: true, // 是否在编辑器左侧显示行号
      fullScreen: true, //当设置为 时true,将使编辑器全屏显示(如占据整个浏览器窗口)。
      mode:language, // 使用模式
      theme: 'material' // 编辑器样式的主题 必须确保.cm-s-[name] 加载定义相应样式的 CSS 文件。默认值为"default",颜色包含在 中codemirror.css。可以一次使用多个主题类,例如将和类"foo bar"都分配给编辑器。cm-s-foocm-s-bar
    };
    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);
     }
  }
  /** 失焦 */
  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());
      }
    }
  };
  return (
    <textarea ref={textareaRef} />
  );
};
export default CodeMirrorEditor;

步骤3:使用CodeMirror组件

在你的应用程序中,使用MyComponent组件来渲染CodeMirror。

import React, { useState } from 'react';
import CodeMirrorEditor from 'CodeMirror';
const CodeEditor: React.FC = () => {
  const [code, setCode] = useState<string>('');
  const handleCodeChange = (value: string) => {
    setCode(value);
  };
  return (
    <div>
      <CodeMirrorEditor
        value=[code]
        language="javascript"
        onChange={handleCodeChange}
      />
      <pre>[code]</pre>
    </div>
  );
};
export default CodeEditor;

步骤4:添加样式

在添加了CodeMirror所需的样式。

.CodeMirror {
  height: 300px;
}

注册Js代码提示

因为上面完整的基础代码已有,下面的代码我只写一些需要额外加进去的部分。关键字可以自己添加,这里只是给个例子看看。当然也可以添加其他语言的提示,registerHelper函数的第二个参数就是所配置的语言,和editorConfig 里面的mode保持一致。

// 注册JavaScript代码提示
const registerHelp = () =>{
	CodeMirror.registerHelper('hint', 'javascript', (editor, options) => {
	  const cursor = editor.getCursor();
	  const token = editor.getTokenAt(cursor);
	  const word = token.string;
	  // 假设你的关键字列表存储在keywords数组中
	  const keywords = ['if', 'else', 'for', 'while', 'function', 'class'];
	  const list = keywords.filter((keyword) => keyword.startsWith(word));
	  return {
	    list,
	    from: CodeMirror.Pos(cursor.line, token.start),
	    to: CodeMirror.Pos(cursor.line, token.end),
	  };
	});
}

1、需要将上面的代码放在初始化codeMirror之上

useEffect(() => {
    const textarea = textareaRef.current;
    if (!textarea) return;
    registerHelp(); // 注册代码提示
    initCodeMirror();
    return () => {
      // 清理和销毁编辑器实例
      editorRef.current?.toTextArea();
    };
  }, []);

2、在codemirrorValueChange函数里加入下面代码

 /** 编辑内容变化 */
  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 === '+input') {
      CodeMirror.commands.autocomplete(editor.current, undefined, {
        completeSingle: false,
      });
    }
    if (change.origin !== 'setValue') {
      if (props.onChange) {
        props.onChange(doc.getValue());
      }
    }
  };

使用了 CodeMirror库的autocomplete命令来触发自动完成功能。

CodeMirror.commands.autocomplete接受三个参数:

  • editor.current:一个CodeMirror编辑器实例,它是你创建的编辑器对象的引用。
  • 第二个参数是可选的,用于指定触发自动完成的原因。可以传入一个字符串作为原因,例如"explicit"表示显式触发,或者传入undefined表示由编辑器自动触发。
  • 第三个参数是可选的配置对象,用于自动完成的选项。在这里,{ completeSingle: false }设置了completeSingle选项为false,表示自动完成功能不会在只有一个建议项时立即完成,而是等待更多的输入或手动触发。

更多配置请自行去官网文档查看https://codemirror.net/5/doc/manual.html#config

到此这篇关于React+TypeScript项目中使用CodeMirror的方法的文章就介绍到这了,更多相关React+TypeScript项目使用CodeMirror内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于CSS实现MaterialUI按钮点击动画并封装成 React 组件

    基于CSS实现MaterialUI按钮点击动画并封装成 React 组件

    笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, ant-design-vue, iView等成熟的UI框架, react生态的ant-design, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和复杂度,使开发者更专注于实现业务逻辑和服务化
    2021-11-11
  • 浅谈react-router@4.0 使用方法和源码分析

    浅谈react-router@4.0 使用方法和源码分析

    这篇文章主要介绍了浅谈react-router@4.0 使用方法和源码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • react项目自行配置热更新的实现

    react项目自行配置热更新的实现

    本文主要介绍了react项目自行配置热更新的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • 深入理解react 组件类型及使用场景

    深入理解react 组件类型及使用场景

    这篇文章主要介绍了深入理解react 组件类型及使用场景,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • 浅谈对于react-thunk中间件的简单理解

    浅谈对于react-thunk中间件的简单理解

    这篇文章主要介绍了浅谈对于react-thunk中间件的简单理解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • useEvent显著降低Hooks负担的原生Hook

    useEvent显著降低Hooks负担的原生Hook

    这篇文章主要为大家介绍了useEvent显著降低Hooks负担的原生Hook示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 渐进式源码解析React更新流程驱动

    渐进式源码解析React更新流程驱动

    这篇文章主要为大家介绍了渐进式源码解析React更新流程驱动详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • React可定制黑暗模式切换开关组件

    React可定制黑暗模式切换开关组件

    这篇文章主要为大家介绍了React可定制黑暗模式切换开关组件示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 使用React手写一个对话框或模态框的方法示例

    使用React手写一个对话框或模态框的方法示例

    这篇文章主要介绍了使用React手写一个对话框或模态框的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • React Ref Callback使用场景最佳实践详解

    React Ref Callback使用场景最佳实践详解

    这篇文章主要为大家介绍了React Ref Callback使用场景最佳实践详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01

最新评论