1、安装依赖
安装codemirror
依赖包:
$ pnpm install codemirror
2、创建挂载点
新建codeMirror.vue
文件:
<template>
<div ref="codeEditor"></div>
</template>
3、最小编辑器
使用minimalSetup
模块创建:
// codeMirror.vue
<script setup>
import { minimalSetup, EditorView } from 'codemirror'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
doc: 'console.log("hello, world")',
extensions: [minimalSetup],
parent: codeEditor.value
})
})
</script>
效果如下:
4、编辑器简要入门
CodeMirror 编辑器可以分为两个主要组件:
-
EditorState
是一个状态对象,用于维护构成文档的数据结构和修改。 -
EditorView
是一个显示适配器,它将状态转换为可以看到并与之交互的内容,它还将这些交互转换为状态更新。 -
codemirror
包提供EditorView
,但它不提供EditorState
。相反,它提供了两个扩展包(minimalSetup
和basicSetup
),旨在通过牺牲一些可配置性来快速入门。 -
通常,
extensions
属性直接提供给EditorState
,但当没有单独的状态实例时,可以将其作为快捷方式传递给EditorView
。 -
minimalSetup
只包含一些你可能需要的核心扩展。用于创建功能编辑器的最小扩展集。仅包括默认键盘映射 、 撤消历史记录 、 特殊字符突出显示 、 自定义选择绘制和默认突出显示样式 。 -
如果想从
codemirror
包中获得更完整的体验,应该使用basicSetup
模块。
5、简易编辑器
使用basicSetup
模块创建:basicSetup
模块确实预先配置了很多漂亮的功能。最不需要真正将它们联系在一起的是语言模块。语言模块包括用于标记代码的解析器、用于设置标记样式的主题以及用于快捷方式(如注释掉行)的命令。
// codeMirror.vue
<script setup>
import { basicSetup, EditorView } from 'codemirror'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
doc: 'console.log("hello, world")',
extensions: [basicSetup],
parent: codeEditor.value
})
})
</script>
效果如下:自带行号等功能...
6、语言包: JavaScript 包
6.1 安装
$ pnpm install @codemirror/lang-javascript
6.2 导入
导入 javascript
模块并将其添加到 extensions
数组中:
// codeMirror.vue
<script setup>
import { basicSetup, EditorView } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'//引入
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
doc: 'console.log("hello, world")',
extensions: [
basicSetup,
javascript()//加到`extensions` 数组中
],
parent: codeEditor.value
})
})
</script>
测试是否生效:使用 Cmd + /
或 Ctrl + /
(许多编辑器中的默认设置)来切换行注释。
7、将 EditorState
与 EditorView
结合使用
7.1 安装
$ pnpm install @codemirror/state @codemirror/view
7.2 替换 EditorView
使用从@codemirror/view
导入的 EditorView
:
// codeMirror.vue
<script setup>
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'//引入
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
doc: 'console.log("hello, world")',
extensions: [
basicSetup,
javascript()
],
parent: codeEditor.value
})
})
</script>
7.3 导入 EditorState
- 导入
EditorState
并将其实例传递给EditorView
下的state
属性。 - 与
EditorView
不同,EditorState
具有私有构造函数,因此必须使用EditorState.create
对其进行初始化。 - 将
doc
和extensions
属性移动到EditorState
进行初始值定义。 parent
由EditorView
管理,因为它与状态的显示方式直接相关。
<script setup>
// codeMirror.vue
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'
import { EditorState } from '@codemirror/state'//引入
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
parent: targetElement,
state: EditorState.create({
doc: initialText,
extensions: [basicSetup, javascript()],
})
})
})
</script>
8、自定义拓展
basicSetup
不可配置。将 basicSetup
替换为其关联的模块。
8.1 安装
安装组成 basicSetup
模块的拓展:
$ pnpm install @codemirror/autocomplete @codemirror/commands @codemirror/language @codemirror/lint @codemirror/search
8.2 导入并注册
<script setup>
// codeMirror.vue
import { basicSetup } from 'codemirror'
import { EditorState } from '@codemirror/state'
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
import { autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete'
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'
import { bracketMatching, defaultHighlightStyle, foldGutter, foldKeymap, indentOnInput, syntaxHighlighting } from '@codemirror/language'
import { lintKeymap } from '@codemirror/lint'
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'
import { crosshairCursor, drawSelection, dropCursor, EditorView, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap, lineNumbers, rectangularSelection } from '@codemirror/view'
const codeEditor = ref()
onMounted(() => {
new EditorView({
parent: targetElement,
state: EditorState.create({
doc: initialText,
extensions: [
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
dropCursor(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
...lintKeymap,
]),
javascript(),
],
})
})
})
</script>
一切正常的话,效果和5一样;
9、只读编辑器
官方案例:Read-Only Editor
//基于7的代码进行修改:
<script setup>
// codeMirror.vue
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'
import { EditorState } from '@codemirror/state'
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
onMounted(() => {
new EditorView({
parent: targetElement,
state: EditorState.create({
doc: initialText,
extensions: [basicSetup, javascript(), EditorState.readOnly.of(true)],// EditorState.readOnly.of(true)
})
})
})
</script>
10、获取编辑器内容
<script setup>
// codeMirror.vue
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'
import { EditorState } from '@codemirror/state'
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
let Editor = ref() //编辑器实例
onMounted(() => {
Editor.value = new EditorView({
parent: targetElement,
state: EditorState.create({
doc: initialText,
extensions: [basicSetup, javascript(), EditorState.readOnly.of(true)],
})
})
})
//获取编辑器内容
function getCode() {
return Editor.value.state.doc.toString()
}
</script>
11、更新编辑器内容
官方案例:Document Changes
<script setup>
// codeMirror.vue
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'
import { EditorState } from '@codemirror/state'
import { javascript } from '@codemirror/lang-javascript'
import { onMounted, ref } from 'vue'
const codeEditor = ref()
let Editor = ref() //编辑器实例
onMounted(() => {
Editor.value = new EditorView({
parent: targetElement,
state: EditorState.create({
doc: initialText,
extensions: [basicSetup, javascript(), EditorState.readOnly.of(true)],
})
})
})
//获取编辑器内容
function getCode() {
return Editor.value.state.doc.toString()
}
// 更新编辑器的内容
function update() {
const ins = Editor.value
ins.dispatch({
changes: {
from: 0,
to: ins.state.doc.length, // 结束的位置
insert: `待展示的内容`
}
})
}
</script>
12、配置主题
官方案例:Styling