fix: 解决编辑器的问题

This commit is contained in:
奔跑的面条
2022-07-06 14:13:27 +08:00
parent 47f6fc87c7
commit 9e6873e1da
7 changed files with 160 additions and 109 deletions
+70 -33
View File
@@ -1,46 +1,83 @@
import { ref, onBeforeUnmount, nextTick } from 'vue'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
// import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
// import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
export const useMonacoEditor = (language = 'json') => {
export const useMonacoEditor = (language = 'javascript') => {
let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null
let initReadOnly = false
const updateVal = async (val: string) => {
monacoEditor?.setValue(val)
setTimeout(async () => {
initReadOnly && monacoEditor?.updateOptions({ readOnly: false })
// await monacoEditor?.getAction('editor.action.formatDocument')?.run()
initReadOnly && monacoEditor?.updateOptions({ readOnly: true })
}, 100)
const el = ref<HTMLElement | null>(null)
// @ts-ignore
self.MonacoEnvironment = {
getWorker(_: any, label: string) {
if (label === 'json') {
return new jsonWorker()
}
// if (label === 'css' || label === 'scss' || label === 'less') {
// return new cssWorker()
// }
// if (label === 'html' || label === 'handlebars' || label === 'razor') {
// return new htmlWorker()
// }
if (label === 'typescript' || label === 'javascript') {
return new tsWorker()
}
return new editorWorker()
}
}
const createEditor = (
el: HTMLElement | null,
editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}
) => {
if (monacoEditor) {
return
}
// 格式化
const onFormatDoc = async () => {
await monacoEditor?.getAction('monacoEditor.action.formatDocument')?.run()
}
// 更新
const updateVal = (val: string) => {
nextTick(async () => {
monacoEditor?.setValue(val)
initReadOnly && monacoEditor?.updateOptions({ readOnly: false })
await onFormatDoc()
initReadOnly && monacoEditor?.updateOptions({ readOnly: true })
})
}
// 创建实例
const createEditor = (editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}) => {
if (!el.value) return
const javascriptModel = monaco.editor.createModel('', language)
initReadOnly = !!editorOption.readOnly
monacoEditor =
el &&
monaco.editor.create(el, {
language,
minimap: { enabled: false },
theme: 'vs-dark',
multiCursorModifier: 'ctrlCmd',
scrollbar: {
verticalScrollbarSize: 8,
horizontalScrollbarSize: 8
},
tabSize: 2,
automaticLayout: true, // 自适应宽高
...editorOption
})
// 创建
monacoEditor = monaco.editor.create(el.value, {
model: javascriptModel,
minimap: { enabled: true },
roundedSelection: false,
theme: 'vs-dark',
multiCursorModifier: 'ctrlCmd',
scrollbar: {
verticalScrollbarSize: 8,
horizontalScrollbarSize: 8
},
tabSize: 2,
fontSize: 16, //字体大小
autoIndent: 'advanced', //自动布局
automaticLayout: true, // 自适应宽高
...editorOption
})
return monacoEditor
}
const onFormatDoc = () => {
monacoEditor?.getAction('editor.action.formatDocument').run()
}
// 卸载
onBeforeUnmount(() => {
if (monacoEditor) monacoEditor.dispose()
})
return {
el,
updateVal,
getEditor: () => monacoEditor,
createEditor,
+52 -62
View File
@@ -1,75 +1,65 @@
<template>
<div class="editor-area" :style="{ width, height }">
</div>
<div ref="el" class="editor-area" :style="{ width, height }"></div>
</template>
<script lang='ts'>
import { defineComponent, ref } from 'vue'
<script lang="ts" setup>
import { onMounted, watch, PropType } from 'vue'
import { useMonacoEditor } from './index.hook'
export default defineComponent({
props: {
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '90vh'
},
language: {
type: String,
default: 'json'
},
preComment: {
type: String,
default: ''
},
modelValue: {
type: String,
default: ''
},
editorOptions: {
type: Object,
default: () => ({})
},
const props = defineProps({
width: {
type: String as PropType<string>,
default: '100%'
},
watch: {
modelValue(val) {
val !== this.getEditor()?.getValue() && this.updateMonacoVal(val)
}
height: {
type: String as PropType<string>,
default: '90vh'
},
setup(props) {
const { updateVal, getEditor, createEditor, onFormatDoc } = useMonacoEditor(props.language)
const isFull = ref(false)
return {
isFull,
updateVal,
getEditor,
createEditor,
onFormatDoc
}
language: {
type: String as PropType<string>,
default: 'javascript'
},
methods: {
updateMonacoVal(_val?: string) {
const { modelValue, preComment } = this.$props
const val = preComment ? `${preComment}\n${_val || modelValue}` : (_val || modelValue)
this.updateVal(val)
}
preComment: {
type: String as PropType<string>,
default: ''
},
mounted() {
if (this.$el) {
const monacoEditor = this.createEditor(this.$el, this.$props.editorOptions)
this.updateMonacoVal()
monacoEditor!.onDidChangeModelContent(() => {
this.$emit('update:modelValue', monacoEditor!.getValue())
})
monacoEditor!.onDidBlurEditorText(() => {
this.$emit('blur')
})
}
modelValue: {
type: String as PropType<string>,
default: ''
},
editorOptions: {
type: Object as PropType<object>,
default: () => ({})
}
})
const emits = defineEmits(['blur', 'update:modelValue'])
const { el, updateVal, getEditor, createEditor } = useMonacoEditor(props.language)
const updateMonacoVal = (_val?: string) => {
const { modelValue, preComment } = props
const val = preComment ? `${preComment}\n${_val || modelValue}` : _val || modelValue
updateVal(val)
}
onMounted(() => {
const monacoEditor = createEditor(props.editorOptions)
monacoEditor!.onDidChangeModelContent(() => {
emits('update:modelValue', monacoEditor!.getValue())
})
monacoEditor!.onDidBlurEditorText(() => {
emits('blur')
})
updateMonacoVal()
})
watch(
() => props.modelValue,
(val: string) => {
val !== getEditor()?.getValue() && updateMonacoVal(val)
}
)
</script>
<style lang="scss" scoped>
@@ -81,4 +71,4 @@ export default defineComponent({
padding-left: 0;
box-sizing: border-box;
}
</style>
</style>