index.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <script setup>
  2. import { ref, onMounted, onBeforeUnmount, watch, nextTick } from "vue";
  3. import loader from "@monaco-editor/loader";
  4. const props = defineProps({
  5. value: String,
  6. language: {
  7. type: String,
  8. default: "python",
  9. },
  10. theme: {
  11. type: String,
  12. default: "vs-light",
  13. },
  14. });
  15. const emit = defineEmits(["update:value"]);
  16. const editorContainer = ref(null);
  17. let editorInstance = null;
  18. // 调试:打印容器尺寸
  19. const logContainerSize = () => {
  20. if (!editorContainer.value) {
  21. // console.log('Editor container not yet mounted');
  22. return;
  23. }
  24. const rect = editorContainer.value.getBoundingClientRect();
  25. // console.log('Container size:', rect.width, 'x', rect.height);
  26. };
  27. // 初始化 Monaco 编辑器
  28. const initEditor = async () => {
  29. const monaco = await loader.init();
  30. // 等待容器渲染完成
  31. await nextTick();
  32. // 添加额外延迟确保布局完成(仅开发时需要)
  33. if (process.env.NODE_ENV === 'development') {
  34. await new Promise(resolve => setTimeout(resolve, 50));
  35. }
  36. // 再次检查尺寸
  37. const rect = editorContainer.value.getBoundingClientRect();
  38. // console.log('Final container size:', rect.width, 'x', rect.height);
  39. editorInstance = monaco.editor.create(editorContainer.value, {
  40. value: props.value || "",
  41. language: props.language,
  42. theme: props.theme,
  43. });
  44. editorInstance.onDidChangeModelContent(() => {
  45. const value = editorInstance.getValue();
  46. emit("update:value", value); // 触发v-model更新
  47. });
  48. // 强制立即布局
  49. editorInstance.layout();
  50. };
  51. // 处理窗口大小变化
  52. const handleResize = () => {
  53. if (editorInstance) {
  54. // console.log('Window resized, updating editor layout');
  55. editorInstance.layout();
  56. }
  57. };
  58. onMounted(() => {
  59. // console.log('Component mounted, initializing editor...');
  60. initEditor();
  61. });
  62. onBeforeUnmount(() => {
  63. // console.log('Component unmounting, disposing editor...');
  64. window.removeEventListener('resize', handleResize);
  65. editorInstance?.dispose();
  66. });
  67. // 监听语言变化
  68. watch(
  69. () => props.language,
  70. (newLanguage) => {
  71. if (editorInstance) {
  72. console.log('Language changed to:', newLanguage);
  73. loader.init().then((monaco) => {
  74. monaco.editor.setModelLanguage(editorInstance.getModel(), newLanguage);
  75. });
  76. }
  77. }
  78. );
  79. // 监听值变化
  80. watch(
  81. () => props.value,
  82. (newValue) => {
  83. if (editorInstance && editorInstance.getValue() !== newValue) {
  84. console.log('Value updated programmatically');
  85. editorInstance.setValue(newValue);
  86. }
  87. }
  88. );
  89. </script>
  90. <template>
  91. <div ref="editorContainer" class="editorContainer"></div>
  92. </template>
  93. <style scoped>
  94. .editorContainer {
  95. height: 400px;
  96. width: 100%;
  97. border: 1px solid #ccc; /* 调试边框 */
  98. position: relative; /* 确保正确的定位上下文 */
  99. }
  100. /* 强制设置 Monaco 容器尺寸 */
  101. .editorContainer :deep(.monaco-editor) {
  102. position: absolute;
  103. top: 0;
  104. left: 0;
  105. right: 0;
  106. bottom: 0;
  107. }
  108. </style>