Vue3集成Monaco Editor时addCommand获取错误props问题求助
Vue3 + Monaco Editor: Cmd+Enter快捷键触发时props始终指向最后一个组件的问题
问题原因
核心问题在于Monaco Editor的addCommand注册的快捷键是全局生效的。当你循环渲染多个CodeEditor组件时,每个组件都用相同的Cmd+Enter组合键注册命令,后注册的命令会直接覆盖之前的。因此无论激活哪个编辑器,触发快捷键时都会执行最后一次注册的回调,自然拿到的是最后一个组件的props.obj.code。
而onDidChangeContent是绑定在每个编辑器的独立Model实例上的,每个组件的回调逻辑完全独立,因此能正确捕获对应组件的props。
解决方案
方案一:使用编辑器onKeyDown事件替代全局命令
直接在每个编辑器实例上监听键盘事件,自行判断快捷键组合,确保每个编辑器的逻辑独立,避免全局覆盖:
修改CodeEditor.vue的onMounted部分:
<script setup lang="ts"> import { defineProps, onMounted, type PropType, ref } from 'vue'; import * as monaco from 'monaco-editor'; import type { MyObj } from './types'; const props = defineProps({ obj: { type: Object as PropType<MyObj>, required: true, } }); const editorContainer = ref<HTMLDivElement | null>(null); onMounted(() => { console.log('onMounted, code = ', props.obj.code); if (!editorContainer.value) { return; } const editor = monaco.editor.create(editorContainer.value, { value: props.obj.code, language: 'python', automaticLayout: true, }); editor.getModel()?.onDidChangeContent(() => { console.log('Content changed, code = ', props.obj.code); }); // 替换addCommand为onKeyDown事件监听 editor.onKeyDown((event) => { const isCmdEnter = (event.ctrlKey || event.metaKey) && event.keyCode === monaco.KeyCode.Enter; if (isCmdEnter) { event.preventDefault(); // 阻止默认行为避免冲突 console.log('Cmd + Enter, code = ', props.obj.code); } }); }); </script>
方案二:给全局命令添加唯一ID并校验激活编辑器
如果一定要使用addCommand,可以给每个命令分配唯一ID,并在回调中检查当前激活的编辑器是否为当前实例:
<script setup lang="ts"> // 导入和props定义不变 onMounted(() => { console.log('onMounted, code = ', props.obj.code); if (!editorContainer.value) { return; } const editor = monaco.editor.create(editorContainer.value, { value: props.obj.code, language: 'python', automaticLayout: true, }); editor.getModel()?.onDidChangeContent(() => { console.log('Content changed, code = ', props.obj.code); }); // 生成唯一命令ID避免全局覆盖 const uniqueCommandId = `custom-cmd-enter-${Math.random()}`; editor.addCommand( uniqueCommandId, () => { // 仅当前激活编辑器为当前实例时执行逻辑 if (monaco.editor.getActiveEditor() === editor) { console.log('Cmd + Enter, code = ', props.obj.code); } }, monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter ); }); </script>
补充说明
Vue的props是响应式代理对象,因此onDidChangeContent的回调能正确获取最新的props值;而addCommand的全局覆盖问题是Monaco Editor的机制导致的,与Vue的响应式逻辑无关。
内容的提问来源于stack exchange,提问作者naivedeveloper
相关产品推荐
相关产品推荐

