File size: 3,830 Bytes
7fc5208 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
<template>
<div ref="editorContainer" class="h-full"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, onBeforeUnmount } from 'vue';
import monaco from '@monaco-editor/loader';
const props = defineProps<{
value: string,
originalValue?: string,
language?: string,
options?: Record<string, any>,
}>();
const emit = defineEmits(['update:value']);
const editorContainer = ref<HTMLElement>();
let editorInstance: any = null;
let monacoInstance: any = null;
let editorModel: any = null;
// 创建编辑器的函数
const createEditor = () => {
if (!editorContainer.value || !monacoInstance) return;
// 如果已存在编辑器实例,先销毁
if (editorInstance) {
editorInstance.dispose();
editorInstance = null;
}
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
const commonOptions = {
language: props.language || 'json',
minimap: { enabled: !isMobile },
fontSize: isMobile ? 16 : 14,
lineNumbers: isMobile ? 'off' as const : 'on' as const,
scrollBeyondLastLine: false,
automaticLayout: true,
...props.options
};
// 每次都创建新模型,确保内容刷新
if (editorModel) {
editorModel.dispose();
}
editorModel = monacoInstance.editor.createModel(props.value, props.language);
if (props.originalValue !== undefined) {
// 创建差异编辑器
const originalModel = monacoInstance.editor.createModel(props.originalValue, props.language);
editorInstance = monacoInstance.editor.createDiffEditor(editorContainer.value, {
...commonOptions,
readOnly: false,
renderSideBySide: true,
ignoreTrimWhitespace: false,
renderOverviewRuler: true,
diffWordWrap: 'on',
});
editorInstance.setModel({
original: originalModel,
modified: editorModel
});
const modifiedEditor = editorInstance.getModifiedEditor();
modifiedEditor.onDidChangeModelContent(() => {
emit('update:value', modifiedEditor.getValue());
});
} else {
// 创建普通编辑器
editorInstance = monacoInstance.editor.create(editorContainer.value, {
...commonOptions,
model: editorModel
});
editorInstance.onDidChangeModelContent(() => {
emit('update:value', editorInstance.getValue());
});
}
};
onMounted(() => {
monaco.init().then(instance => {
monacoInstance = instance;
createEditor();
});
});
// 监听 value 和 originalValue 的变化
watch([() => props.value, () => props.originalValue], ([newVal, newOriginalVal], [oldVal, oldOriginalVal]) => {
// 判断是否需要重建编辑器
const modeChanged =
(oldOriginalVal === undefined && newOriginalVal !== undefined) ||
(oldOriginalVal !== undefined && newOriginalVal === undefined);
if (modeChanged) {
// 编辑器模式变化,重新创建
createEditor();
} else if (editorInstance) {
if (props.originalValue !== undefined) {
// 差异模式下更新内容
const model = editorInstance.getModel();
if (model && model.original && model.original.getValue() !== newOriginalVal) {
model.original.setValue(newOriginalVal || '');
}
if (model && model.modified && model.modified.getValue() !== newVal) {
model.modified.setValue(newVal || '');
}
} else {
// 普通模式下更新内容
if (editorInstance.getValue() !== newVal) {
editorInstance.setValue(newVal || '');
}
}
}
}, { deep: true });
onBeforeUnmount(() => {
if (editorInstance) {
editorInstance.dispose();
}
if (editorModel) {
editorModel.dispose();
}
editorInstance = null;
editorModel = null;
});
</script>
<style scoped>
:deep(.monaco-diff-editor),
:deep(.monaco-editor) {
height: 100%;
}
</style>
|