环境:vue3 + codemirror6
创建一个代码编辑器
<template>
<div ref="cdRef"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from "vue"
import { EditorState } from "@codemirror/state";
import { javascript } from "@codemirror/lang-javascript";
import { EditorView, keymap, lineNumbers } from "@codemirror/view";
import { defaultKeymap, insertTab } from "@codemirror/commands";
const cdRef = ref();
const codeValue = ref('');
const cdView = ref<EditorView>();
// 赋值编辑器的方法,用于作为公共组件时,由父级组件触发编辑器内容的更新
const setInput = (value) => {
if (!cdView.value) return;
cdView.value.dispatch({ changes: { from: 0, to: cdView.value.state.doc.length, insert: value } });
};
const initEditor = () => {
if (cdView.value) {
cdView.value.destroy();
cdView.value = null;
}
const state = EditorState.create({
doc: codeValue.value,
extensions: [
javascript(),
lineNumbers(),// 行号
EditorView.lineWrapping,// 自动换行
keymap.of([
...defaultKeymap,
{
key: 'Tab',
run: insertTab,
},
]),
EditorView.updateListener.of((v) => {
codeValue.value = v.state.doc.toString() // 监测得到的最新内容并更新到监听的容器中
}),
],
});
cdView.value = new EditorView({
state,
parent: cdRef.value
});
}
onMounted(() => {
initEditor()
});
onBeforeUnmount(() => {
if (cdView.value) {
cdView.value.destroy();
cdView.value = null;
}
})
defineExpose({
setInput
});
</script>
这个时候,如果需要实现编辑器为可读(不允许输入)的场景,有如下两种方法:
两种方法均在extensions中添加属性
方法一:
设置EditorState中的readOnly为true,即在extensions的数组中加入EditorState.readOnly.of(true)这一属性。
方法二:
设置EditorView中的editable为false,即在extensions的数组中加入EditorView.editable.of(false)这一属性。
再看codemirror中是这样对readOnly进行说明的
最后一段中说了Not to be confused with EditorView.editable, which controls whether the editor's DOM is set to be editable (and thus focusable).
意思是这个属性不要和EditorView中的editable混淆了,这样是不是说明这两个属性实现的效果是不同的?答案是肯定的,这两个属性的区别在于设置EditorState.readOnly的编辑器为不可编辑,但是还是会有光标闪烁,而设置了EditorView.editable的编辑器为不可编辑且不会有光标闪烁。当然,这里的不可编辑指的是不可在编辑器中实时编辑,如果通过调用示例代码中的setInput方法强制给编辑器赋值也是可以更新编辑器的内容的。