vue-cli3 , elementui ,typescript ,使用monaco-editor
npm install monaco-editor -S封装了一个组件// \src\components\MonacoEditor.vue<template><div ref="container" class="app-monaco"></div></template><script lang="ts">import { Compon
npm install monaco-editor -S
封装了一个组件
// \src\components\MonacoEditor.vue
<template>
<div ref="container" class="app-monaco"></div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import * as monaco from "monaco-editor";
import { createWrapper } from "@vue/test-utils";
@Component
export default class MonacoEditor extends Vue {
// 组件属性,用v-model来传递。
// 代码的内容
@Prop()
public value!: string;
// monaco 实例
private editor: monaco.editor.IStandaloneCodeEditor | null = null;
// 监听value变化,若变化则设置到 monaco 实例中
@Watch("value")
private async onValueChanged(newValue: string) {
if (this.editor == null) return;
// 更改editor内容
this.editor.setValue(newValue);
this.editor.getAction("editor.action.formatDocument").run();
}
mounted() {
// 创建 monaco 实例
this.editor = monaco.editor.create(<HTMLElement>this.$refs.container, {
/**
* 根据你们自己的喜欢,将下面的内容作为prop
*/
value: this.value,
// readOnly: true,
// theme: "vs-dark",
language: "typescript",
});
// 监听内容改变,改变之后更新value
// @ts-ignore
this.editor.onDidChangeModelContent((event: any) => {
//编辑器内容changge事件
// @ts-ignore
this.$emit("input", this.editor.getValue());
});
}
/**
* 销毁monaco实例
*/
destroyEditor() {
if (this.editor == null) return;
// 销毁编辑器
this.editor.dispose();
this.editor = null;
}
/**
* vue 组件销毁钩子
*/
beforeDestroy() {
this.destroyEditor();
}
}
</script>
<style scoped lang="scss">
.app-monaco {
width: 100%;
min-height: 300px;
border: 1px solid grey;
}
</style>
使用相关代码
<template>
<div class="interface-serarch">
<el-row>
<el-col :span="16" :offset="4">
<h1>模拟断言脚本</h1>
<el-card class="box-card">
<div slot="header" class="clearfix">
<h4 style="padding: 0px; margin: 0px; display: inline-block">
基本测试
</h4>
<el-button style="float: right; padding: 3px 0" type="text">
测试
</el-button>
</div>
</el-card>
</el-col>
<el-col :span="16" :offset="4" style="margin-top: 50px">
<MonacoEditor v-model="codeStr"></MonacoEditor>
</el-col>
<el-col :span="16" :offset="4" style="margin-top: 50px">
<pre>{{ codeStr }}</pre>
<el-button
style="float: right; padding: 3px 0"
type="text"
@click="resetCode"
>
重置
</el-button>
</el-col>
</el-row>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import MonacoEditor from "@/components/MonacoEditor.vue";
@Component({ components: { MonacoEditor } })
export default class AssertionTest extends Vue {
private codeStr: string = [
"function x() {",
'\tconsole.log("Hello world!");',
"}",
].join("\n");
private resetCode() {
this.codeStr = 'var sss="sdfs"';
}
}
</script>
页面效果
如下图,还蛮美好的,但实际上糟糕透了,报着错,还没有提示
editorSimpleWorker.js?ccf6:459
Uncaught (in promise) Error: Unexpected usage
at EditorSimpleWorker.loadForeignModule (editorSimpleWorker.js?ccf6:459)
at eval (webWorker.js?af50:38)
errors.js?fdcc:12
Uncaught Error: Unexpected usage
Error: Unexpected usage
at EditorSimpleWorker.loadForeignModule (editorSimpleWorker.js?ccf6:459)
at eval (webWorker.js?af50:38)
at eval (errors.js?fdcc:12)
参考了下官方的列子,发现我少一些代码,通过代码也确定了一个事情,就是有些东西没有加载到【下面这个代码可以不用抄】【因为后面我的特殊性下面路径我加了/js/】【☞☞☞参考】
// 参考 https://github.com/microsoft/monaco-editor-samples/blob/master/browser-esm-webpack-typescript/src/index.ts
// @ts-ignore
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
if (label === 'json') {
return './js/json.worker.bundle.js';
}
if (label === 'css' || label === 'scss' || label === 'less') {
return './js/css.worker.bundle.js';
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return './js/html.worker.bundle.js';
}
if (label === 'typescript' || label === 'javascript') {
return './js/ts.worker.bundle.js';
}
return './js/editor.worker.bundle.js';
}
};
加上去之后错误的确发生了变化,如下
editor.worker.bundle.js:1 Uncaught SyntaxError: Unexpected token '<'
上面的代码的确被执行了,并且Monaco给出了反应,他去请求了对应的资源。无奈vue-cli有一个默认配置,请求到404的时候返回index.html,所以被当做js执行的他,报了个<的错误。
继续发现官方samples的特别之处,被我发现了webpack.config.js有一串代码【☞☞☞参考】
// 参考 https://github.com/microsoft/monaco-editor-samples/blob/master/browser-esm-webpack-typescript/webpack.config.js
entry: {
app: './index.js',
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
'css.worker': 'monaco-editor/esm/vs/language/css/css.worker',
'html.worker': 'monaco-editor/esm/vs/language/html/html.worker',
'ts.worker': 'monaco-editor/esm/vs/language/typescript/ts.worker'
}
亏我吧vue-cli关于webpack的配置资料翻了一波,配置之后有变化,但还是泡沫【下面这个代码可以不用抄】【这个的修改需要重启npm run】【cli3添加webpack相关配置参考】
// vue.config.js
module.exports = {
configureWebpack: {
// externals: {
// vue: 'Vue',
// 'vue-router': 'VueRouter',
// 'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
// 'json.worker': 'monaco-editor/esm/vs/language/json/json.worker',
// 'css.worker': 'monaco-editor/esm/vs/language/css/css.worker',
// 'html.worker': 'monaco-editor/esm/vs/language/html/html.worker',
// 'ts.worker': 'monaco-editor/esm/vs/language/typescript/ts.worker'
// // axios: 'axios'
// }
entry: {
'editor.worker.bundle': 'monaco-editor/esm/vs/editor/editor.worker.js',
'json.worker.bundle': 'monaco-editor/esm/vs/language/json/json.worker',
'css.worker.bundle': 'monaco-editor/esm/vs/language/css/css.worker',
'html.worker.bundle': 'monaco-editor/esm/vs/language/html/html.worker',
'ts.worker.bundle': 'monaco-editor/esm/vs/language/typescript/ts.worker'
}
},
chainWebpack: config => {
// 移除 prefetch 插件
config.plugins.delete('prefetch')
}
}
但不幸的是,依然不行。这里就不加原文了,他说的意思是webpack4以上就不用加插件了,我就真的没有加,其实只是缺了那个插件,可笑的是我看到官方samples也没有明确说明要那个东西,最后还是加上插件解决问题的
安装依赖
npm install monaco-editor-webpack-plugin
修改vue.config.js,【这个的修改需要重启npm run】
// vue.config.js
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
configureWebpack: {
plugins: [
new MonacoWebpackPlugin()
]
},
chainWebpack: config => {
// 移除 prefetch 插件
config.plugins.delete('prefetch')
}
}
哈哈哈,没错,到这里还有一个问题,就是v-model和watch把自己坑了一波,在互相影响设置,改造上面封装的Monaco组件
// 代码就不贴完整ts文件了,我也坑坑你们,哈哈哈
/**
* 定义vm参考变量
*/
private vmValue!: string;
/**
* 监听的时候丢弃自身的触发
*/
// vmValue==newValue 的时候,其实就是monaco使用input更新value造成的Watch,所以要丢弃
if (this.vmValue != newValue) {
this.vmValue = this.value;
// 更改editor内容
this.editor.setValue(newValue);
this.editor.getAction("editor.action.formatDocument").run();
}
/**
* 初始化
*/
this.vmValue = this.value;
/**
* 设置的时候
*/
this.vmValue = this.editor.getValue();
await this.$nextTick();
this.$emit("input", this.vmValue);
完美了!!!
更多推荐
所有评论(0)