代码编辑器实践

微软官方编辑器:https://github.com/microsoft/monaco-editor
官方提供的整合教程:https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md

1)安装编辑器

1
npm install monaco-editor

2)vue-cli 项目(webpack 项目)整合 monaco-editor(编辑器)。

先安装 monaco-editor(编辑器)-webpack-plugin(https://github.com/microsoft/monaco-editor/blob/main/webpack-plugin/README.md):

1
npm install monaco-editor-webpack-plugin

在 vue.config.js 中配置 webpack 插件:

全量加载:

1
2
3
4
5
6
7
8
const { defineConfig } = require("@vue/cli-service");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack(config) {
config.plugin("monaco").use(new MonacoWebpackPlugin());
},
});

按需加载:

1
2
3
4
5
6
7
8
9
10
11
12
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
module.exports = {
chainWebpack: config => {
config.plugin('monaco-editor').use(MonacoWebpackPlugin, [
{
// Languages are loaded on demand at runtime
languages: ['json', 'go', 'css', 'html', 'java', 'javascript', 'less', 'markdown', 'mysql', 'php', 'python', 'scss', 'shell', 'redis', 'sql', 'typescript', 'xml'], // ['abap', 'apex', 'azcli', 'bat', 'cameligo', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dart', 'dockerfile', 'ecl', 'fsharp', 'go', 'graphql', 'handlebars', 'hcl', 'html', 'ini', 'java', 'javascript', 'json', 'julia', 'kotlin', 'less', 'lexon', 'lua', 'm3', 'markdown', 'mips', 'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo', 'perl', 'pgsql', 'php', 'postiats', 'powerquery', 'powershell', 'pug', 'python', 'r', 'razor', 'redis', 'redshift', 'restructuredtext', 'ruby', 'rust', 'sb', 'scala', 'scheme', 'scss', 'shell', 'solidity', 'sophia', 'sql', 'st', 'swift', 'systemverilog', 'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml'],
features: ['format', 'find', 'contextmenu', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover' , 'documentSymbols'] //['accessibilityHelp', 'anchorSelect', 'bracketMatching', 'caretOperations', 'clipboard', 'codeAction', 'codelens', 'colorPicker', 'comment', 'contextmenu', 'coreCommands', 'cursorUndo', 'dnd', 'documentSymbols', 'find', 'folding', 'fontZoom', 'format', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover', 'iPadShowKeyboard', 'inPlaceReplace', 'indentation', 'inlineHints', 'inspectTokens', 'linesOperations', 'linkedEditing', 'links', 'multicursor', 'parameterHints', 'quickCommand', 'quickHelp', 'quickOutline', 'referenceSearch', 'rename', 'smartSelect', 'snippets', 'suggest', 'toggleHighContrast', 'toggleTabFocusMode', 'transpose', 'unusualLineTerminators', 'viewportSemanticTokens', 'wordHighlighter', 'wordOperations', 'wordPartOperations']
}
])
}
}

如何使用 Monaco Editor(编辑器)?查看示例教程:

https://microsoft.github.io/monaco-editor/playground.html?source=v0.40.0#example-creating-the-editor-hello-world
整合教程参考:http://chart.zhenglinglu.cn/pages/2244bd/#%E5%9C%A8-vue-%E4%B8%AD%E4%BD%BF%E7%94%A8

注意 ,monaco editor(编辑器) 在读写值的时候,要使用 toRaw(编辑器实例)的语法来执行操作,否则会卡死。

示例整合代码如下:

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
<template>
<div id="code-editor" ref="codeEditorRef" style="min-height: 400px" />
{{ value }}
<a-button @click="fillValue">填充值</a-button>
</template>
<script setup lang="ts">
import * as monaco from "monaco-editor";
import { onMounted, ref, toRaw } from "vue";
const codeEditorRef = ref();
const codeEditor = ref();
const value = ref("hello world");
const fillValue = () => {
if (!codeEditor.value) {
return;
}
// 改变值
toRaw(codeEditor.value).setValue("新的值");
};
onMounted(() => {
if (!codeEditorRef.value) {
return;
}
// Hover on each property to see its docs!
codeEditor.value = monaco.editor.create(codeEditorRef.value, {
value: value.value,
language: "java",
automaticLayout: true,
colorDecorators: true,
minimap: {
enabled: true,
},
readOnly: false,
theme: "vs-dark",
// lineNumbers: "off",
// roundedSelection: false,
// scrollBeyondLastLine: false,
});
// 编辑 监听内容变化
codeEditor.value.onDidChangeModelContent(() => {
console.log("目前内容为:", toRaw(codeEditor.value).getValue());
});
});
</script>
<style scoped></style>

与 Md 编辑器一样,也要接受父组件的传值,把显示的输入交给父组件去控制,从而能够让父组件实时得到用户输入的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 定义组件属性类型
*/
interface Props {
value: string;
handleChange: (v: string) => void;
}
/**
* 给组件指定初始值
*/
const props = withDefaults(defineProps<Props>(), {
value: () => "",
handleChange: (v: string) => {
console.log(v);
},
});

代码编辑器实践
https://xmas-nnnut.github.io/2023/11/15/代码编辑器实践/
作者
Xmas-nnnut
发布于
2023年11月15日
许可协议