|
@@ -1,86 +1,88 @@
|
|
|
<template>
|
|
|
- <div id="editorContainer"></div>
|
|
|
+ <div :id="editorId" class="editorContainer"></div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted, watch, toRaw } from 'vue';
|
|
|
-import * as monaco from 'monaco-editor';
|
|
|
+import { ref, onMounted, onUnmounted, watch, computed, toRaw } from 'vue'
|
|
|
+import * as monaco from 'monaco-editor'
|
|
|
|
|
|
const props = defineProps({
|
|
|
- modelValue: String, // v-model 绑定
|
|
|
- value: String, // 兼容传统 value 绑定
|
|
|
+ value: String,
|
|
|
language: String,
|
|
|
-});
|
|
|
+})
|
|
|
|
|
|
-const emit = defineEmits(['update:modelValue', 'change']);
|
|
|
+const emit = defineEmits(['change'])
|
|
|
+const editor = ref(null)
|
|
|
+const editorId = computed(() => `editor_${Math.random().toString(36).slice(2, 11)}`)
|
|
|
|
|
|
-const editor = ref(null);
|
|
|
-let isUpdatingFromParent = false; // 添加防止死循环的锁
|
|
|
+const getEditorValue = () => toRaw(editor.value)?.getValue() || ''
|
|
|
|
|
|
-// 获取当前值
|
|
|
-const getCurrentValue = () => props.modelValue ?? props.value;
|
|
|
-const getEditorValue = () => toRaw(editor.value)?.getValue() || '';
|
|
|
+let resizeObserver = null
|
|
|
|
|
|
-// 监听父组件传来的值变化(用于外部更新编辑器)
|
|
|
-watch(
|
|
|
- () => getCurrentValue(),
|
|
|
- (newValue) => {
|
|
|
- const editorVal = getEditorValue();
|
|
|
- const normalize = (s) => (s || '').trim();
|
|
|
+onMounted(() => {
|
|
|
+ const el = document.getElementById(editorId.value)
|
|
|
+
|
|
|
+ if (!el) {
|
|
|
+ // console.warn('[MonacoEdit]找不到容器元素')
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- if (editor.value && normalize(newValue) !== normalize(editorVal)) {
|
|
|
- console.log('外部更新编辑器内容', newValue);
|
|
|
- console.log('当前编辑器内容', editorVal);
|
|
|
+ const initEditor = () => {
|
|
|
+ if (editor.value || el.clientWidth === 0 || el.clientHeight === 0) return
|
|
|
|
|
|
- isUpdatingFromParent = true;
|
|
|
+ // console.log('[MonacoEdit]尺寸可用,初始化编辑器')
|
|
|
|
|
|
- // 设置值
|
|
|
- editor.value.setValue(newValue || '');
|
|
|
+ monaco.editor.defineTheme('custom-light', {
|
|
|
+ base: 'vs',
|
|
|
+ inherit: true,
|
|
|
+ rules: [],
|
|
|
+ colors: {
|
|
|
+ 'editorGutter.background': '#EEEEEE',
|
|
|
+ },
|
|
|
+ })
|
|
|
|
|
|
- // 等当前宏任务结束后再解除锁
|
|
|
- queueMicrotask(() => {
|
|
|
- isUpdatingFromParent = false;
|
|
|
- console.log('编辑器内容已更新', editor.value.getValue());
|
|
|
- });
|
|
|
- } else {
|
|
|
- console.log('内容相同,跳过更新');
|
|
|
+ editor.value = monaco.editor.create(el, {
|
|
|
+ value: props.value || '',
|
|
|
+ language: props.language || 'python',
|
|
|
+ minimap: { enabled: true },
|
|
|
+ colorDecorators: true,
|
|
|
+ readOnly: false,
|
|
|
+ theme: 'custom-light',
|
|
|
+ automaticLayout: true,
|
|
|
+ })
|
|
|
+
|
|
|
+ editor.value.onDidChangeModelContent(() => {
|
|
|
+ emit('change', getEditorValue())
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log('[MonacoEdit]初始化完成')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用 ResizeObserver 监听尺寸变化
|
|
|
+ resizeObserver = new ResizeObserver(() => {
|
|
|
+ if (el.clientWidth > 0 && el.clientHeight > 0 && !editor.value) {
|
|
|
+ initEditor()
|
|
|
}
|
|
|
+ })
|
|
|
+
|
|
|
+ resizeObserver.observe(el)
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ if (editor.value) {
|
|
|
+ editor.value.dispose()
|
|
|
+ editor.value = null
|
|
|
}
|
|
|
-);
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- monaco.editor.defineTheme("custom-light", {
|
|
|
- base: "vs",
|
|
|
- inherit: true,
|
|
|
- rules: [],
|
|
|
- colors: {
|
|
|
- "editorGutter.background": "#EEEEEE",
|
|
|
- },
|
|
|
- });
|
|
|
-
|
|
|
- editor.value = monaco.editor.create(document.getElementById('editorContainer'), {
|
|
|
- value: getCurrentValue() || '',
|
|
|
- language: props.language || 'python',
|
|
|
- minimap: { enabled: true },
|
|
|
- colorDecorators: true,
|
|
|
- readOnly: false,
|
|
|
- theme: "custom-light",
|
|
|
- automaticLayout: true,
|
|
|
- });
|
|
|
-
|
|
|
- // 编辑器内容变化时触发
|
|
|
- editor.value.onDidChangeModelContent(() => {
|
|
|
- if (isUpdatingFromParent) return; // 阻止外部设置引起的触发
|
|
|
-
|
|
|
- const newValue = getEditorValue();
|
|
|
- emit('update:modelValue', newValue); // 通知父组件更新
|
|
|
- emit('change', newValue);
|
|
|
- });
|
|
|
-});
|
|
|
+ if (resizeObserver) {
|
|
|
+ resizeObserver.disconnect()
|
|
|
+ resizeObserver = null
|
|
|
+ }
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style>
|
|
|
-#editorContainer {
|
|
|
+.editorContainer {
|
|
|
height: 400px !important;
|
|
|
}
|
|
|
</style>
|