文章目录
- 前言
- 使用codeMirror
- 注册Js代码提示
前言
之前做需求用到过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;
步骤:使用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><CodeMirrorEditorvalue={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