Monaco-editor,一个vs code 编辑器,需要将其继承到项目。不说闲话了,直接上代码。
npm地址:https://www.npmjs.com/package/monaco-editor
中文文档:https://aydk.site/editor/
安装:
javascript
pnpm add monaco-editor -S
pnpm add vite-plugin-monaco-editor -D
配置:
vite.config.ts
javascript
import { defineConfig} from 'vite'
// vs code 编辑器配置
import monacoEditorPlugin from 'vite-plugin-monaco-editor'
// https://vitejs.dev/config/
export default ({ mode }) => {
return defineConfig({
plugins: [
monacoEditorPlugin({
languageWorkers: ['editorWorkerService', 'typescript', 'json', 'html']
})
]
})
}
封装:
首先先封装个hook如下:
@/hooks/useMonacoEditor.hook.ts
javascript
import * as monaco from 'monaco-editor'
import useCommonStore from '@/store/common'
import { ref, nextTick, onBeforeUnmount } from 'vue'
export function useMonacoEditor(language: string = 'javascript') {
// 编辑器示例
let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null
// 目标元素
const monacoEditorRef = ref<HTMLElement | null>(null)
// 创建实例
function createEditor(editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}) {
if(!monacoEditorRef.value) return
monacoEditor = monaco.editor.create(monacoEditorRef.value, {
// 初始模型
model: monaco.editor.createModel('', language),
// 是否启用预览图
minimap: { enabled: true },
// 圆角
roundedSelection: true,
// 主题
theme: useCommonStore().mode == 'dark' ? 'vs-dark' : 'vs',
// 主键
multiCursorModifier: 'ctrlCmd',
// 滚动条
scrollbar: {
verticalScrollbarSize: 8,
horizontalScrollbarSize: 8
},
// 行号
lineNumbers: 'on',
// tab大小
tabSize: 2,
//字体大小
fontSize: 16,
// 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
autoIndent: 'advanced',
// 自动布局
automaticLayout: true,
...editorOption
})
return monacoEditor
}
// 格式化
async function formatDoc() {
await monacoEditor?.getAction('editor.action.formatDocument')?.run()
}
// 数据更新
function updateVal(val: string) {
nextTick(() => {
if(getOption(monaco.editor.EditorOption.readOnly)) {
updateOptions({ readOnly: false })
}
monacoEditor?.setValue(val)
setTimeout(async () => {
await formatDoc()
}, 10)
})
}
// 配置更新
function updateOptions(opt: monaco.editor.IStandaloneEditorConstructionOptions) {
monacoEditor?.updateOptions(opt)
}
// 获取配置
function getOption(name: monaco.editor.EditorOption) {
return monacoEditor?.getOption(name)
}
// 获取实例
function getEditor() {
return monacoEditor
}
// 页面离开 销毁
onBeforeUnmount(() => {
if(monacoEditor) {
monacoEditor.dispose()
}
})
return {
monacoEditorRef,
createEditor,
getEditor,
updateVal,
updateOptions,
getOption,
formatDoc
}
}
然后调用上面 useMonacoEditor 封装editor编辑器组件
@/components/MonacoEditor/index.vue
javascript
<template>
<div ref="monacoEditorRef" :style="monacoEditorStyle"></div>
</template>
<script setup lang="ts">
import { useMonacoEditor } from '@/hooks'
import { onMounted, computed, watch } from 'vue'
const props = withDefaults(defineProps<{
width?: string | number,
height?: string | number,
language?: string,
editorOption?: Object,
modelValue: string
}>(), {
width: '100%',
height: '100%',
language: 'javascript',
editorOption: () => ({}),
modelValue: ''
})
const emits = defineEmits<{
(e: 'blue'): void,
(e: 'update:modelValue', val: string): void
}>()
const monacoEditorStyle = computed(() => {
return {
width: typeof props.width === 'string' ? props.width : props.width + 'px',
height: typeof props.height === 'string' ? props.height : props.height + 'px'
}
})
const { monacoEditorRef, createEditor, updateVal, updateOptions, getEditor } = useMonacoEditor(props.language)
onMounted(() => {
const monacoEditor = createEditor(props.editorOption)
updateMonacoVal(props.modelValue)
monacoEditor?.onDidChangeModelContent(() => {
emits('update:modelValue', monacoEditor!.getValue())
})
monacoEditor?.onDidBlurEditorText(() => {
emits('blue')
})
})
watch(() => props.modelValue, () => {
updateMonacoVal(props.modelValue)
})
function updateMonacoVal(val: string) {
if(val !== getEditor()?.getValue()) {
updateVal(val)
}
}
defineExpose({ updateOptions })
</script>
组件使用:
html
<div class="edit-container">
<MonacoEditor ref="MonacoEditRef" v-model="editJson" language="json" />
</div>
<script setup lang="ts">
import MonacoEditor from '@/components/MonacoEditor/index.vue'
import { ref } from 'vue'
let editJson = ref('')
const MonacoEditRef = ref<InstanceType<typeof MonacoEditor>>()
//MonacoEditRef.value!.updateOptions({ theme: 'vs' }) 调用子组件方法修改配置
</script>