monaco-editor使用amd方式在vue中使用
- Published on
本文最近一次更新于 1436 个天前,其中的内容很可能已经有所发展或是发生改变。
前言
monaco-editor
是微软vscode的核心编辑器,除了在客户端中使用外,官方也支持在web端使用。由于我的博客想要一个能像vscode一样编辑页面的编辑器,所以采用了monaco-editor
实现了一个页面编辑器。本文记录了monaco-editor
在vue项目中的使用记录。
初探
原本是想直接引用vue封装好的库vue-monaco-editor,单后来发现不管是vue的库还是react的库react-monaco-editor都是基于monaco的esm的方式引入,这就导致了这些库只支持英文的菜单栏展示,不支持多语言。 想要向vscode一样支持多语言,可以以AMD方式引入monaco-editor
,在esm上没找到合适快捷的方式,尝试多次后,我最终还是使用AMD方式引入。
2023.10.10 更新 在 react 的库里, https://github.com/suren-atoyan/monaco-react 作者用 typescript 重写的微软的 monaco-editor,可以正常使用 esm 方式引入了
monaco-editor
的AMD方式引入
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<h2>Monaco Editor Localization Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
<script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } });
require.config({
'vs/nls': {
availableLanguages: {
'*': 'zh-cn'
}
}
});
require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('container'), {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'javascript'
});
});
</script>
</body>
</html>
通过cdn引入
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs/editor/editor.main.css" />
</head>
<body>
<h2>Monaco Editor Localization Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script>
self.require = {
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs' },
'vs/nls': { availableLanguages: { '*': 'zh-cn' } }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs/loader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs/editor/editor.main.nls.zh-cn.js"></script>
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs/editor/editor.main.js"></script>
<script>
monaco.editor.create(document.getElementById('container'), {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'javascript'
});
</script>
</body>
</html>
国际化是以下代码实现的
self.require = {
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs' },
'vs/nls': { availableLanguages: { '*': 'zh-cn' } }
};
paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.24.0/min/vs' }
这个对cdn引入的方式很重要的,如果没有就会导致跨域问题。
在vue中使用
amd方式引入后,其实是将monaco挂载到window对象上,在vue上直接使用window.monaco
就可以了。
1.封装成组件
结合vue-monaco-editor
的源码,封装一下编辑器,代码如下:
<!-- monacoEditor -->
<template>
<div class="monaco-editor">
</div>
</template>
<script>
/**
* monacoEditor
* @description:
* @file: index.vue
* @author: example <example@raycloud.com>
* @date: 2021-05-21
*/
import _ from 'lodash'
export default {
name: 'MonacoEditor',
props: {
code: { type: String, default: '// code \n' },
language: { type: String, default: 'javascript' },
theme: { type: String, default: 'vs-dark' }, // vs, hc-black
options: {
type: Object, default: () => {}
},
highlighted: {
type: Array,
default: () => [{
number: 0,
class: ''
}]
},
// 更新频率
changeThrottle: {
type: Number, default: 0
}
},
components: {},
data () {
return {
defaults: {
selectOnLineNumbers: true,
roundedSelection: false,
readOnly: false,
cursorStyle: 'line', // 光标样式
automaticLayout: true, // 自动布局
glyphMargin: true, // 字形边缘
lineNumbersMinChars: 0,
fontSize: 12, // 字体大小
autoIndent: false,
wordWrap: 'wordWrapColumn',
wordWrapColumn: 100
}
}
},
computed: {
editorOptions () {
return Object.assign({}, this.defaults, this.options, {
value: this.code,
language: this.language,
theme: this.theme
})
}
},
watch: {
language () {
window.monaco.editor.setModelLanguage(this.editor.getModel(), this.language)
}
},
methods: {
createEditor () {
this.editor = window?.monaco?.editor.create(this.$el, this.editorOptions)
this.initEditor(this.editor, window.monaco)
},
initEditor (editor, monaco) {
this.editor = editor
this.monaco = monaco
this.editor.onDidChangeModelContent(event => {
this.codeChange(editor, event)
})
this.$emit('mounted', editor)
},
codeChange (editor, ev) {
if (this.codeChangeEmitter) {
this.codeChangeEmitter(editor)
} else {
this.codeChangeEmitter = _.debounce(function (editor) {
this.$emit('codeChange', editor)
}, this.changeThrottle)
}
}
},
created () {
},
mounted () {
this.createEditor()
},
destroyed () {
if (typeof this.editor !== 'undefined') {
this.editor.dispose()
}
}
}
</script>
2.在项目中使用
<template>
<Editor
:code="code"
:language="language"
@codeChange="handleChange"
@mounted="onMounted"
:editorOptions="editorOptions"
style="width: 700px; height: 480px; border: 1px solid grey"
/>
</template>
<script>
import Editor from './xxx/MonacoEditor'
export default {
components: {
Editor
},
data () {
return {
editor: null,
code: '// 默认展示',
language: 'html',
editorOptions: {
},
}
},
methods: {
onMounted (editor) {
this.editor = editor
},
handleChange (editor) {
this.code = editor.getValue()
}
},
}
</script>
3.设置主题 、设置编辑语言高亮支持
例如设置背景,设置主题之类的自定义的实现方式可以参考官方的例子 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-semantic-tokens-provider-example