You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:21:25