概念
monaco是一个可提供在线编辑器的库。
使用
安装
cnpm i monaco-editor -D
因为安装这个库后,我们使用它作出的组件需要用js去编写css所以还需要jss库,这里安装使用在vue上的:
cnpm i vue-jss -S
// 以及vue-jss的依赖包
cnpm i jss jss-preset-default -S
一个使用了monaco的tsx文件
这里是从github上的开源项目嫖过来的文件:
import { defineComponent, ref, onMounted, watch, onBeforeUnmount, shallowReadonly, shallowRef } from 'vue'
import * as Monaco from 'monaco-editor'
import type { PropType, Ref } from 'vue'
import { createUseStyles } from 'vue-jss'
const useStyles = createUseStyles({
container: {
border: '1px solid #eee',
display: 'flex',
flexDirection: 'column',
borderRadius: 5
},
title: {
backgroundColor: '#eee',
padding: '10px 0',
paddingLeft: 20,
},
code: {
flexGrow: 1
}
})
export default defineComponent({
props: {
code: {
type: String as PropType<string>,
required: true
},
onChange: {
type: Function as PropType<(value: string, event: Monaco.editor.IModelContentChangedEvent) => void>,
required: true
},
title: {
type: String as PropType<string>,
required: true
}
},
setup(props) {
// must be shallowRef, if not, editor.getValue() won't work
const editorRef = shallowRef()
const containerRef = ref()
let _subscription: Monaco.IDisposable | undefined
let __prevent_trigger_change_event = false
onMounted(() => {
const editor = editorRef.value = Monaco.editor.create(containerRef.value, {
value: props.code,
language: 'json',
formatOnPaste: true,
tabSize: 2,
minimap: {
enabled: false,
},
})
_subscription = editor.onDidChangeModelContent((event) => {
console.log('--------->', __prevent_trigger_change_event)
if (!__prevent_trigger_change_event) {
props.onChange(editor.getValue(), event);
}
});
})
onBeforeUnmount(() => {
if (_subscription)
_subscription.dispose()
})
watch(() => props.code, (v) => {
const editor = editorRef.value
const model = editor.getModel()
if (v !== model.getValue()) {
editor.pushUndoStop();
__prevent_trigger_change_event = true
// pushEditOperations says it expects a cursorComputer, but doesn't seem to need one.
model.pushEditOperations(
[],
[
{
range: model.getFullModelRange(),
text: v,
},
]
);
editor.pushUndoStop();
__prevent_trigger_change_event = false
}
// if (v !== editorRef.value.getValue()) {
// editorRef.value.setValue(v)
// }
})
const classesRef = useStyles()
return () => {
const classes = classesRef.value
return (
<div class={classes.container}>
<div class={classes.title}><span>{props.title}</span></div>
<div class={classes.code} ref={containerRef}></div>
</div>
)
}
}
})
引用组件
在App.tsx中引用上面的组件:
import { defineComponent, Ref, ref } from "vue";
import { createUseStyles } from "vue-jss"; // 引入开源项目,用js写css
import MonacoEditor from "./components/MonacoEditor"; // 引入别人用monaco写的组件
const toJson = (params: any) => {
return JSON.stringify(params, null, 2); // 保留格式的json转换
};
const schema = {
// schema规则
type: "string",
};
const useStyles = createUseStyles({
// 写样式
editor: {
minHeight: 400,
},
});
export default defineComponent({
setup() {
const schemaRef: Ref<any> = ref(schema); // 取得响应式的schema
const handleCodeChange = (code: string) => {
// 当在页面修改了code后会触发
let schema: any;
try {
schema = JSON.parse(code); // 转换回来
} catch (e) {}
schemaRef.value = schema; // 转换回来
};
const classesRef = useStyles(); // 初始化
return () => {
const classes = classesRef.value;
const code = toJson(schemaRef.value);
return (
<div id="app">
<MonacoEditor
code={code}
onChange={handleCodeChange}
title="Schema"
class={classes.editor}
/>
</div>
);
};
},
});
效果
问题
如果出现无法使用的报错信息(这里已经找不到之前的报错信息是啥了23333,先暂时记录下),大概是说找不到对应的monaco插件啥的,给他装个就是了
cnpm i monaco-editor-webpack-plugin
然后在vue.config.js中:
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
module.exports = {
chainWebpack(config) {
config.plugin("monaco").use(new MonacoWebpackPlugin());
},
};