CodeMirror 使用教程

CodeMirror 是一个功能强大、高度可定制的代码编辑器组件,专为网页应用设计,它被广泛应用于在线代码编辑器、IDE、教程网站等场景。

codemirror使用教程
(图片来源网络,侵删)

本教程将带你一步步了解如何使用 CodeMirror。


目录

  1. 第一部分:快速入门 - 5分钟搭建你的第一个代码编辑器

    • 引入文件
    • 创建 HTML 结构
    • 初始化编辑器
    • 完整示例
    • 关键 API 解析
  2. 第二部分:核心功能详解

    • 配置选项
    • 获取和设置值
    • 事件监听
    • 模式
    • 主题
  3. 第三部分:进阶功能

    codemirror使用教程
    (图片来源网络,侵删)
    • 代码提示/自动补全
    • 代码折叠
    • 行号显示
    • 括号匹配
    • 搜索与替换
    • 只读模式
  4. 第四部分:实战案例 - 构建一个简单的在线代码编辑器

    • 需求分析
    • 实现步骤
    • 完整代码
  5. 第五部分:总结与最佳实践


第一部分:快速入门 - 5分钟搭建你的第一个代码编辑器

引入文件

你需要将 CodeMirror 的 CSS 和 JavaScript 文件引入到你的 HTML 页面中,你可以通过 CDN 或下载本地文件的方式引入。

使用 CDN (推荐):

codemirror使用教程
(图片来源网络,侵删)
<!-- 引入 CodeMirror 的 CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
<!-- 引入主题 CSS (这里以 monokai 主题为例) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/monokai.min.css">
<!-- 引入 CodeMirror 的 JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
<!-- 引入你需要的语言模式 JS (这里以 JavaScript 为例) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>

本地文件:CodeMirror 官网 下载最新版本,然后将相应的 CSS 和 JS 文件放入你的项目中。

创建 HTML 结构

<body> 标签中,创建一个 <textarea> 元素,CodeMirror 会将这个 <textarea> 替换成功能丰富的代码编辑器。

<textarea id="myEditor"></textarea>

初始化编辑器

<script> 标签中,使用 JavaScript 初始化 CodeMirror。

const editor = CodeMirror.fromTextArea(document.getElementById('myEditor'), {
  lineNumbers: true, // 显示行号
  mode: 'javascript', // 设置语言模式
  theme: 'monokai'    // 设置主题
});

完整示例

将以上三部分组合起来,你就可以看到一个可以工作的 JavaScript 代码编辑器了。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">CodeMirror 快速入门</title>
  <!-- 引入 CodeMirror 的 CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
  <!-- 引入主题 CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/monokai.min.css">
  <style>
    /* 给编辑器容器设置一个高度,否则可能不可见 */
    .CodeMirror {
      height: 400px;
      border: 1px solid #ccc;
    }
  </style>
</head>
<body>
  <h1>我的第一个 CodeMirror 编辑器</h1>
  <textarea id="myEditor">// 输入一些 JavaScript 代码
function helloWorld() {
  console.log("Hello, CodeMirror!");
}
helloWorld();</textarea>
  <!-- 引入 CodeMirror 的 JS -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
  <!-- 引入 JavaScript 语言模式 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
  <script>
    // 初始化编辑器
    const editor = CodeMirror.fromTextArea(document.getElementById('myEditor'), {
      lineNumbers: true,       // 显示行号
      mode: 'javascript',      // 语言模式为 JavaScript
      theme: 'monokai',        // 使用 monokai 主题
      indentUnit: 2,           // 缩进单位为2个空格
      lineWrapping: true       // 自动换行
    });
  </script>
</body>
</html>

关键 API 解析

  • CodeMirror.fromTextArea(textareaElement, config): 这是初始化编辑器的核心方法,它接收一个 <textarea> DOM 元素和一个配置对象。
  • lineNumbers: true: 在编辑器左侧显示行号。
  • mode: 'javascript': 指定编辑器的语言模式,CodeMirror 会根据此模式进行语法高亮,你需要引入对应的模式文件。
  • theme: 'monokai': 指定编辑器的视觉主题,你需要引入对应的主题文件。

第二部分:核心功能详解

配置选项

在初始化时,通过配置对象可以精细地控制编辑器的行为。

选项 类型 默认值 描述
lineNumbers boolean false 是否显示行号。
mode string null 语言模式,如 "javascript", "python", "css"
theme string "default" 主题名称,如 "monokai", "material", "one-dark"
indentUnit number 2 缩进的空格数。
indentWithTabs boolean false 是否使用制表符进行缩进。
lineWrapping boolean false 是否自动换行。
smartIndent boolean true 是否智能缩进(新行根据上一行内容自动缩进)。
tabSize number 4 制表符的宽度(空格数)。
readOnly boolean false 是否为只读模式。
autofocus boolean false 页面加载后是否自动聚焦到编辑器。

获取和设置值

编辑器实例提供了获取和设置内容的方法。

  • 获取值

    const currentValue = editor.getValue(); // 获取编辑器的全部文本内容
    console.log(currentValue);
  • 设置值

    editor.setValue("let newCode = 'Hello, world!';\nconsole.log(newCode);");
  • 获取光标位置

    const cursorPos = editor.getCursor(); // 返回 { line: number, ch: number }
    console.log(`当前光标在第 ${cursorPos.line} 行,第 ${cursorPos.ch} 个字符`);
  • 设置光标位置

    editor.setCursor({ line: 3, ch: 0 }); // 将光标移动到第4行开头

事件监听

编辑器在发生特定事件时会触发回调函数。

  • "change": 编辑器内容发生变化时触发(非常常用)。

    editor.on("change", function(instance, changeObj) {
      // changeObj 描述了变化
      // { from: {line, ch}, to: {line, ch}, removed: [...], text: [...] }
      console.log("编辑器内容已更新!");
      // 可以在这里执行保存、验证等操作
    });
  • "cursorActivity": 光标或选中区域发生变化时触发。

    editor.on("cursorActivity", function() {
      console.log("光标移动了或选中区域改变了。");
    });

模式

模式是 CodeMirror 的核心,它决定了如何对代码进行语法高亮,CodeMirror 支持数十种语言模式。

  • 如何使用: 在引入 JS 文件后,在 config 中设置 mode 即可。
    <!-- 引入 Python 模式文件 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/python/python.min.js"></script>
    const pythonEditor = CodeMirror.fromTextArea(document.getElementById('pythonEditor'), {
      mode: 'python',
      lineNumbers: true
    });

主题

主题决定了编辑器的颜色方案和外观。

  • 如何使用: 引入 CSS 文件后,在 config 中设置 theme 即可。
    <!-- 引入 Material 主题 -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/material.min.css">
    const materialEditor = CodeMirror.fromTextArea(document.getElementById('materialEditor'), {
      theme: 'material', // 使用 material 主题
      lineNumbers: true
    });

第三部分:进阶功能

代码提示/自动补全

CodeMirror 本身不提供自动补全功能,但它与一个名为 CodeMirror-addon-hint 的官方插件无缝集成。

步骤:

  1. 引入文件

    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/hint/show-hint.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/hint/show-hint.min.css">
  2. 配置编辑器

    const editor = CodeMirror.fromTextArea(myTextarea, {
      // ... 其他配置
      extraKeys: {
        "Ctrl-Space": "autocomplete" // 绑定 Ctrl+Space 触发自动补全
      }
    });
    // 注册提示源
    CodeMirror.registerHelper("hint", "javascript", function(editor) {
      // 这里可以写更复杂的逻辑,从你的项目中获取变量/函数列表
      const word = editor.getTokenAt(editor.getCursor()).string;
      const list = ["function", "var", "let", "const", "console", "log"];
      return {
        list: list.filter(item => item.startsWith(word)),
        from: CodeMirror.Pos(editor.getCursor().line, editor.getCursor().ch - word.length),
        to: CodeMirror.Pos(editor.getCursor().line, editor.getCursor().ch)
      };
    });
    // 当按下触发键时,显示提示
    editor.on("inputRead", function() {
      if (editor.state.completionActive) return;
      CodeMirror.showHint(editor, CodeMirror.hint.javascript);
    });

代码折叠

通过 foldGutter 插件实现。

  1. 引入文件

    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/foldcode.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/foldgutter.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/fold/foldgutter.min.css">
  2. 配置编辑器

    const editor = CodeMirror.fromTextArea(myTextarea, {
      // ... 其他配置
      lineNumbers: true,
      foldGutter: true, // 开启折叠 gutter
      extraKeys: {
        "Ctrl-Q": "toggleFold" // 绑定 Ctrl-Q 切换折叠
      }
    });

行号显示

非常简单,只需在配置中设置 lineNumbers: true

括号匹配

默认开启,无需额外配置,它会高亮显示匹配的括号。

搜索与替换

通过 search 插件实现。

  1. 引入文件

    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/search/search.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/search/searchcursor.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/dialog/dialog.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/addon/dialog/dialog.min.css">
  2. 配置编辑器

    const editor = CodeMirror.fromTextArea(myTextarea, {
      // ... 其他配置
      extraKeys: {
        "Ctrl-F": "find",           // 查找
        "F3": "findNext",           // 查找下一个
        "Shift-F3": "findPrev",     // 查找上一个
        "Ctrl-H": "replace",        // 替换
        "Alt-F": "findPersistent"   // 持久查找(界面更好看)
      }
    });

只读模式

只需在配置中设置 readOnly: true


第四部分:实战案例 - 构建一个简单的在线代码编辑器

我们将创建一个包含编辑器、代码高亮、主题切换和运行按钮的简单在线代码编辑器。

需求:

  1. 一个代码编辑器,默认内容为 JavaScript 代码。
  2. 可以切换编辑器主题(如 defaultmonokai)。
  3. 点击 "运行" 按钮,在控制台打印代码的执行结果。

实现步骤:

  1. HTML 结构

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>简易在线代码编辑器</title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/theme/monokai.min.css">
      <style>
        body { font-family: sans-serif; }
        #editor-container { height: 400px; border: 1px solid #ccc; }
        #controls { margin: 10px 0; }
        select, button { padding: 5px; }
        #output { margin-top: 10px; padding: 10px; background: #f4f4f4; border: 1px solid #ddd; min-height: 50px; }
      </style>
    </head>
    <body>
      <h1>简易在线代码编辑器</h1>
      <div id="controls">
        <label for="theme-select">选择主题: </label>
        <select id="theme-select">
          <option value="default">Default</option>
          <option value="monokai">Monokai</option>
        </select>
        <button id="run-btn">运行代码</button>
      </div>
      <div id="editor-container">
        <textarea id="code-editor">// 在这里输入你的 JavaScript 代码
    function greet(name) {
    return `Hello, ${name}!`;
    }

console.log(greet("CodeMirror"));

  <h3>输出:</h3>
  <pre id="output"></pre>
  <!-- JS 文件 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
  <script src="app.js"></script>
</body>
</html>
```
  1. JavaScript 逻辑 (app.js)

    document.addEventListener('DOMContentLoaded', () => {
      // 1. 初始化编辑器
      const editor = CodeMirror.fromTextArea(document.getElementById('code-editor'), {
        mode: 'javascript',
        theme: 'default',
        lineNumbers: true,
        indentUnit: 2,
        lineWrapping: true
      });
      // 2. 获取 DOM 元素
      const themeSelect = document.getElementById('theme-select');
      const runButton = document.getElementById('run-btn');
      const outputElement = document.getElementById('output');
      // 3. 主题切换功能
      themeSelect.addEventListener('change', (e) => {
        editor.setOption('theme', e.target.value);
      });
      // 4. 运行代码功能
      runButton.addEventListener('click', () => {
        // 清空之前的输出
        outputElement.textContent = '';
        // 重定向 console.log
        const originalLog = console.log;
        const logs = [];
        console.log = (...args) => {
          logs.push(args.map(arg => String(arg)).join(' '));
        };
        try {
          // 使用 Function 构造函数安全地执行代码
          const userCode = editor.getValue();
          const func = new Function(userCode);
          func(); // 执行用户代码
          // 显示捕获到的日志
          if (logs.length > 0) {
            outputElement.textContent = logs.join('\n');
          } else {
            outputElement.textContent = '代码执行完成,无输出。';
          }
        } catch (error) {
          // 捕获并显示错误
          outputElement.textContent = `错误: ${error.message}`;
        } finally {
          // 恢复原始的 console.log
          console.log = originalLog;
        }
      });
    });

第五部分:总结与最佳实践

  1. 按需引入: 不要一次性引入所有插件和模式,只引入你项目需要的,这可以显著减少页面加载体积。
  2. 性能考虑: 对于非常大的文件,可以考虑启用 viewportMargin 选项来优化渲染性能。
  3. 版本选择: CodeMirror 5.x 和 6.x 是两个完全不同的版本,目前绝大多数教程和插件都是基于 5.x 的,除非你有特殊需求,否则建议使用稳定且生态丰富的 x 版本
  4. 事件驱动: 充分利用 "change" 事件来监听用户输入,实现实时保存、语法检查等功能。
  5. 配置隔离: 如果一个页面有多个编辑器,最好为它们创建不同的配置对象,以避免样式和行为上的冲突。

希望这份详细的教程能帮助你顺利上手 CodeMirror!