二丫讲梵 二丫讲梵
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)

二丫讲梵

行者常至,为者常成
首页
  • 最佳实践
  • 迎刃而解
  • Nginx
  • Php
  • Zabbix
  • AWS
  • Prometheus
  • Grafana
  • CentOS
  • Systemd
  • Docker
  • Rancher
  • Ansible
  • Ldap
  • Gitlab
  • GitHub
  • Etcd
  • Consul
  • RabbitMQ
  • Kafka
  • MySql
  • MongoDB
  • OpenVPN
  • KVM
  • VMware
  • Other
  • ELK
  • K8S
  • LLM
  • Nexus
  • Jenkins
  • 随写编年
  • 家人物语
  • 追忆青春
  • 父亲的朋友圈
  • 电影音乐
  • 效率工具
  • 博客相关
  • Shell
  • 前端实践
  • Vue学习笔记
  • Golang学习笔记
  • Golang编程技巧
  • 学习周刊
  • Obsidian插件周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • json2go (opens new window)
    • gopher (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)
  • Shell编程

  • Go编程笔记

  • 前端编程笔记

    • 基于codemirror在页面中嵌入代码编辑器
      • 1,基础信息
      • 2,用法简言
        • 1,高亮语言
        • 2,主题选择
        • 3,案例分享
        • 4,最终效果
      • 3,原生使用
      • 4,其他参数
        • 1,常用配置
        • 2,编辑器事件
      • 5,参考
    • npm install时报错Failed at the node-sass-4.14.1 postinstall script的问题及解决
    • 前端开发小笔记--在数组中给字段添加值与删除字段的操作
  • Go学习笔记

  • Vue-21年学习笔记

  • Vue-22年重学笔记

  • 编程世界
  • 前端编程笔记
二丫讲梵
2020-08-06
目录

基于codemirror在页面中嵌入代码编辑器

文章发布较早,内容可能过时,阅读注意甄别。

# 1,基础信息

  • 名字:codemirror
  • 资料
    • Git 地址:https://github.com/codemirror/codemirror
    • 官方文档:https://codemirror.net/
    • 支持的高亮语言:https://codemirror.net/mode/
    • 主题选择:https://codemirror.net/demo/theme.html#default
  • 衍生
    • vue-codemirror (opens new window)
    • vue-ele-form (opens new window)
    • 一些示例:https://github.surmon.me/vue-codemirror/

# 2,用法简言

官方文档的阅读性并不是很好,因此简单记录一些几个使用的注意点。没有尝试过直接引用原生的包的效果,目前是基于 ele-form (opens new window) 这个二次封装的库来做的。不过有许多东西,还可以基于原生的一些特性,进行自定义。

# 1,高亮语言

一般直接拷贝上边示例中的一些案例即可满足需求,如果想要自定义,有如下注意点,因为我需要的是 shell 输入框,因此引入语言改成如下内容:

// language
import "codemirror/mode/shell/shell.js";
1
2

需要注意的一个点是,在引用中配置(options)参数(mode)时,并不是 shell,而是 x-sh,这个可以在高亮语言中点击 (opens new window)进去的示例下边看到,因为这个上下不一致,让我踩了挺长时间的坑(因为网上大多示例都是采用的 JavaScript 高亮,而这个模块儿引入又刚好是text/javascript,因此造成了一定的误导),截图示例如下:

img

# 2,主题选择

主题选择可以根据如下 demo (opens new window) 选择适合自己的,引入主题的方式如下:

// theme css
import "codemirror/theme/base16-light.css";
1
2

然后在引用中配置(options)参数(theme)中定义即可,这里测试名字是上下一致的,没有其他坑点。不过我引入的 shell 语言,测试之后发现默认的主题反而最好看,因此不需引入 css,直接设置为default即可。

# 3,案例分享

接下来分享一下我个人的使用案例,整理内容,大致如下:

<template>
  <!-- 代码输入区域 -->
  <ele-form
    :formDesc="formDesc"
    v-model="formData"
    :request-fn="handleRequest"
    @request-success="handleRequestSuccess"
  ></ele-form>
</template>
<script>
// 引入外部包
import EleForm from "vue-ele-form";
import EleFormCodemirror from "vue-ele-form-codemirror";
// language
import "codemirror/mode/shell/shell.js";
// require active-line.js
import "codemirror/addon/selection/active-line.js";
// closebrackets
import "codemirror/addon/edit/closebrackets.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/emacs.js";
export default {
  data() {
    return {
      formData: {},
      // 定制样式
      formDesc: {
        option: {
          label: "命令", // 说明文字
          type: "codemirror", // 选择这个类型
          tabSize: 4,
          line: true,
          theme: "default", // 主题选择默认
          mode: "text/x-sh", // 此处定义高亮语言风格
          lineNumbers: true,
          styleActiveLine: true,
          autoCloseBrackets: true,
        },
      },
    };
  },
  methods: {
    handleRequest(data) {
      console.log(data);
      return Promise.resolve();
    },
    handleRequestSuccess() {
      this.$message.success("发送成功");
    },
    handleSelectionChange(val) {
      console.log("选择成功");
      this.multipleSelection = val;
    },
  },
};
</script>
<style>
.CodeMirror-focused .cm-matchhighlight {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
  background-position: bottom;
  background-repeat: repeat-x;
}
.cm-matchhighlight {
  background-color: lightgreen;
}
.CodeMirror-selection-highlight-scrollbar {
  background-color: green;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

在自己的项目中,可根据实际情况将引入的内容放到公共的部分。

# 4,最终效果

出来的效果大致如下:

img

# 3,原生使用

上边通过引入了一个第三方组件来实现的,其实也可以直接通过 vue-codemirror (opens new window) 来实现,效果基本上是差不多的。

代码大概如下:

<template>
  <!-- 代码输入区域 -->
  <codemirror v-model="formData.task_content" :options="cmOptions" />
</template>
<script>
// language
import "codemirror/mode/shell/shell.js";
// require active-line.js
import "codemirror/addon/selection/active-line.js";
// closebrackets
import "codemirror/addon/edit/closebrackets.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/emacs.js";
export default {
  data() {
    return {
      formData: {},
      cmOptions: {
        tabSize: 4,
        mode: "text/x-sh",
        lineNumbers: true,
        line: true,
        matchBrackets: true,
        scrollbarStyle: "overlay",
        theme: "default",
      },
    };
  },
  methods: {},
};
</script>
<style></style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

这种更加原生的状态,更能方便我们将输入框作为表单的一环来应用,不过默认情况下,代码的行间距有点大,光标太大,不是很好看,可以通过如下代码进行美化:

.code-mirror {
  font-size: 13px;
  line-height: 150%;
}
1
2
3
4

然后将这个样式引用即可。

# 4,其他参数

# 1,常用配置

  • keyMap: string 配置快捷键。默认值为 default,即 codemorrir.js 内部定义。其它在 key map 目录下。
  • extraKeys: object 给编辑器绑定与前面 keyMap 配置不同的快捷键。
  • lineWrapping: boolean 在长行时文字是换行 (wrap) 还是滚动(scroll),默认为滚动(scroll)。
  • lineNumbers: boolean 是否在编辑器左侧显示行号。
  • firstLineNumber: integer 行号从哪个数开始计数,默认为 1 。
  • lineNumberFormatter: function(line: integer) → string 使用一个函数设置行号。
  • gutters: array<string> 用来添加额外的 gutter(在行号 gutter 前或代替行号 gutter)。值应该是 CSS 名称数组,每一项定义了用于绘制 gutter 背景的宽度(还有可选的背景)。为了能明确设置行号 gutter 的位置(默认在所有其它 gutter 的右边),也可以包含 CodeMirror-linenumbers 类。类名是用于传给 setGutterMarker 的键名 (keys)。
  • fixedGutter: boolean 设置 gutter 跟随编辑器内容水平滚动(false)还是固定在左侧(true 或默认)。
  • scrollbarStyle: string 设置滚动条。默认为”native”,显示原生的滚动条。核心库还提供了”null” 样式,此样式会完全隐藏滚动条。Addons 可以设置更多的滚动条模式。
  • coverGutterNextToScrollbar: boolean 当 fixedGutter 启用,并且存在水平滚动条时,在滚动条最左侧默认会显示 gutter,当此项设置为 true 时,gutter 会被带有 CodeMirror-gutter-filler 类的元素遮挡。
  • inputStyle: string 选择 CodeMirror 处理输入和焦点的方式。核心库定义了 textarea 和 contenteditable 输入模式。在移动浏览器上,默认是 contenteditable,在桌面浏览器上,默认是 textarea。在 contenteditable 模式下对 IME 和屏幕阅读器支持更好。
  • readOnly: boolean|string 编辑器是否只读。如果设置为预设的值 “nocursor”,那么除了设置只读外,编辑区域还不能获得焦点。
  • showCursorWhenSelecting: boolean 在选择时是否显示光标,默认为 false。
  • lineWiseCopyCut: boolean 启用时,如果在复制或剪切时没有选择文本,那么就会自动操作光标所在的整行。
  • undoDepth: integer 最大撤消次数,默认为 200(包括选中内容改变事件) 。
  • historyEventDelay: integer 在输入或删除时引发历史事件前的毫秒数。
  • tabindex: integer 编辑器的 tabindex。
  • autofocus: boolean 是否在初始化时自动获取焦点。默认情况是关闭的。但是,在使用 textarea 并且没有明确指定值的时候会被自动设置为 true。

低级选项,下面的选项仅用于一些特殊情况。

  • dragDrop: boolean 是否允许拖放,默认为 true。
  • allowDropFileTypes: array<string> 默认为 null。当设置此项时,只接收包含在此数组内的文件类型拖入编辑器。文件类型为 MIME 名称。
  • cursorBlinkRate: number 光标闪动的间隔,单位为毫秒。默认为 530。当设置为 0 时,会禁用光标闪动。负数会隐藏光标。
  • cursorScrollMargin: number 当光标靠近可视区域边界时,光标距离上方和下方的距离。默认为 0 。
  • cursorHeight: number 光标高度。默认为 1,也就是撑满行高。对一些字体,设置 0.85 看起来会更好。
  • resetSelectionOnContextMenu: boolean 设置在选择文本外点击打开上下文菜单时,是否将光标移动到点击处。默认为 true。
  • workTime, workDelay: number 通过一个假的后台线程高亮 workTime 时长,然后使用 timeout 休息 workDelay 时长。默认为 200 和 300 (啥玩意儿这个)
  • pollInterval: number 指明 CodeMirror 向对应的 textarea 滚动(写数据)的速度(获得焦点时)。大多数的输入都是通过事件捕获,但是有的输入法(如 IME)在某些浏览器上并不会生成事件,所以使用数据滚动。默认为 100 毫秒。
  • flattenSpans: boolean 默认情况下,CodeMirror 会将使用相同 class 的两个 span 合并成一个。通过设置此项为 false 禁用此功能。
  • addModeClass: boolean 当启用时(默认禁用),会给每个标记添加额外的表示生成标记的 mode 的以 cm-m 开头的 CSS 样式类。例如,XML mode 产生的标记,会添加 cm-m-xml 类。
  • maxHighlightLength: number 当需要高亮很长的行时,为了保持响应性能,当到达某些位置时,编辑器会直接将其他行设置为纯文本 (plain text)。默认为 10000,可以设置为 Infinity 来关闭此功能。
  • viewportMargin: integer 指定当前滚动到视图中内容上方和下方要渲染的行数。这会影响到滚动时要更新的行数。通常情况下应该使用默认值 10。可以设置值为 Infinity 始终渲染整个文档。注意:这样设置在处理大文档时会影响性能。

# 2,编辑器事件

编辑器实例会触发以下这些事件。其中的 instance 参数总是指向编辑器本身。

  • change: (instance: CodeMirror, changeObj: object) 每当编辑器内容发生变化时触发。参数 changeObj 是一个 {from, to, text, removed, origin} 对象,包含内容变化的信息。其中 from 和 to 是内容改变发生的起止位置(改变发生之前),举个例子,如果改变始于第 19 行之初,则 from 为{ch:0, line:18}。text 替换起止位置之间内容的文字,按行分割开,组成数组。removed 则是被替换掉的内容。这个事件会在 operation 临结束前,在 DOM 更新之前触发。
  • changes: (instance: CodeMirror, changes: array:) 类似于 change 事件,不过是在每次 operation 后,将改变一次过打包成数组传出来。而展现这些改变,又将出发一次新的 operation。
  • beforeChange: (instance: CodeMirror, changeObj:object) 这个事件在内容改变生效前触发,它的 handler 可以此来修改或取消这次改变。其中的 changeObj 对象有 from, to, text 属性。它还包含一个 cancel()方法,用于取消这次改变,而且如果这次改变不是来自撤销 (undo) 与重做 (redo) 操作的画,它还会有一个 update(from, to, text)方法,用来修改这次改变。update 方法的 3 个参数都不是必填的,可以不传入,以直接使用原先的值。注意:你不该在 beforeChange 的 handler 中做任务会导致 document 或其视觉表现的操作。
  • cursorActivity: (instance: CodeMirror) 每当光标或内容选择移动时出发,因此编辑器中任务内容的改变也会出发。
  • keyHandled: (instance: CodeMirror, name: string, event: Event) 每当一个快捷键被通过 key map handled 时触发。name 是被 handled 的键(例如”ctrl-x” 或者 “‘q’”),而 event 则是 DOM 的 keydown 或 keypress 事件。
  • inputRead: (instance: CodeMirror, changeObj: object) 每当被因此对 textarea 中有新的输入被读取到时触发(可能是来自键盘输入或粘贴)。
  • electricInput: (instance: CodeMirror, line: integer) 当输入的文字匹配 mode 的 electric 模式时触发,这会导致该行的缩进发生改变。
  • beforeSelectionChange: (instance: CodeMirror, obj: {range, origin, update})
  • viewportChange: (instance: CodeMirror, from: number, to: number) 当可视区发生变化时触发(这可能是由于滚动、编辑内容等原因造成)。其参数 from 和 to 给出了可视区新的起始位置。
  • swapDoc: (instance: CodeMirror, oldDoc: Doc) 当编辑器的 document 被使用 swapDoc 方法更换掉时触发。
  • gutterClick: (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event) 每当编辑器的 gutter 被点击时触发。其参数分别为编辑器实例;为被点击的行数,从 0 开始计数;+ gutter 的 CSS class 名;mousedown 的原始事件。
  • gutterContextMenu: (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event) 每当编辑器的 gutter 收到 contextmenu 事件时触发。与 gutterClick 不同的是,最后一个参数是 contextmenu 事件。你可以 preventDefault 这个事件,这会通知 CodeMirror 不再进一步 handle。
  • focus: (instace: CodeMirror) 当编辑器获得焦点时触发。
  • blur: (instance: CodeMirror) 当编辑器失去焦点时触发。
  • scroll: (instance: CodeMirror) 当编辑器滚动时触发。
  • scrollCursorIntoView (instance: CodeMirror, event: Event)
  • update: (instance: CodeMirror) 每当 CodeMirror 更新它的 DOM 展示时触发。
  • renderLine (instance: CodeMirror, line: LineHandle, element: Element) 每当一行需要被绘制(重绘)成 DOM 时触发。它触发在 DOM 元素建立好之后,但在加入 document 之前。handler 可以改动该元素的样式,或是为其添加 event handlers,但不该尝试改变编辑器的状态。
  • mousedown, dbclick, touchstart, contextmenu, keydown, keypress, keyup, cut, copy ,paste, dragstart, dragenter, dragover, dragleave, drop: (instance: CodeMirror, event: Event) 当 CodeMirrorhandle 这些 DOm 事件时触发。你可以 preventDefault 这些事件,也可以把它们的 codemirrorIgnore 属性设为真值,以告知 CodeMirror 不要再继续 handle。文档对象 (Document objects, CodeMirror.Doc 的实例)
  • change: (doc: CodeMirror.Doc, changeObj: object) 每当 document 发生改变时触发。参数 changeObj 类似于编辑器 change 事件的 changeObj。
  • beforeChange: (doc: CodeMirror.Doc, change: object) 参见编辑器的同名事件。
  • cursorActivity: (doc: CodeMirror.Doc) 每当 document 中的光标和选区变化时触发。
  • beforeSelectionChange: (doc: CodeMirror.Doc, selection: {head, anchor}) 参见编辑器的同名事件。
  • Line handles as returned by, for example, getLineHandle 可以理解为行对象
  • delete: () 当行对象被删除时触发。
  • change: (line: LineHandle, changeObj: object) 当行对象中的内容发生改变(但这一行并没有被完全删除)时触发。changeObj 跟编辑器对象的同名事件一样。

# 5,参考

  • https://www.jianshu.com/p/1c7bde873970
微信 支付宝
上次更新: 2024/07/04, 22:40:37
过年时鼓捣xirang框架遇到的前后端问题两则
npm install时报错Failed at the node-sass-4.14.1 postinstall script的问题及解决

← 过年时鼓捣xirang框架遇到的前后端问题两则 npm install时报错Failed at the node-sass-4.14.1 postinstall script的问题及解决→

最近更新
01
学习周刊-总第216期-2025年第25周
06-20
02
睡着的人不关灯
06-12
03
学习周刊-总第215期-2025年第24周
06-12
更多文章>
Theme by Vdoing | Copyright © 2017-2025 | 点击查看十年之约 | 浙ICP备18057030号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式