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

Vue3中使用mitt事件总线结合下拉框出现TypeError问题求助

解决Vue中Mitt事件总线触发时的TypeError问题

问题场景

已在main.js中配置Mitt作为全局事件总线:

import { createApp } from "vue";
import App from './App.vue'
import mitt from "mitt";
const emitter = mitt();
const app = createApp(App);
app.config.globalProperties.emitter = emitter;
app.mount("#app");

子组件ComboBox通过事件总线发布事件:

<template>
    <div class= "combobox">
        <!-- 注意:原for属性写法错误,需改为Vue绑定语法 -->
        <label :for="selector_name">
            <p>{{ selector_title }}</p>
        </label>
        <select :name="selector_name" :id="selector_id" :disabled="disabled" @change="onChange">
            <option v-for="(opt, index) in selector_options" :key="`opt ${index}`">
                {{ opt }}
            </option>
        </select>
    </div>
</template>

<script>
export default {
    name: 'ComboBox',
    data() { 
        return {
            disabled: false,
        };
    },
    props: {
        selector_title: {
            type: String,
            required: true
        },
        selector_name: {
            type: String,
            required: true
        },
        selector_id: {
            type: String,
            default: "combobox"
        },
        selector_options: {
            type: Array,
            required: true
        },
    },
    methods: {
        onChange(event){
            this.emitter.emit('lock-combobox', { id: this.selector_id });
        },
    },
}
</script>

父组件Controls订阅事件,但触发下拉框选项时抛出Uncaught TypeError: undefined has no properties错误:

<template>
<div id="controls" class="param">
    <div class="control" id="combobox1">
        <ComboBox
            selector_title = "Pattern"
            selector_name = "pattern"
            :selector_options="['complex', 'simple']"
            selector_id="combo1"
            ref="combo1"
        />
    </div>
    <div class="control" id="combobox2">
        <ComboBox
            selector_title = "Hand"
            selector_name = "pattern"
            :selector_options="['Left', 'Right']"
            selector_id="combo2"
            ref="combo2"
        />
    </div>
    <div class="control" id="speedslider">
        <SpeedSlider/>
    </div>
    <div class="control" id="startstop">
        <StartStopButton/>
    </div>
    <div class="control" id="emergency">
        <Emergency/>
    </div>
</div>
</template>

<script>
import ComboBox from '../components/ComboBox.vue';

export default {
    name: "Controls",
    components: {
        ComboBox,
    },
    created() {
        this.emitter.on('lock-combobox', (event) => {
            // 原写法逻辑错误,导致undefined访问
            this.$refs.event.id.disabled = true;
        });
    },
}
</script>

错误原因

  1. 父组件事件回调中错误使用this.$refs.event.id:event是我们传递的自定义参数对象,并非$refs中的组件引用名称,因此this.$refs.event返回undefined,访问其属性触发TypeError。
  2. 直接操作DOM的disabled属性不符合Vue数据驱动的设计,应通过修改子组件的响应式数据控制状态。

修复方案

修改父组件的事件回调逻辑,通过传递的id匹配对应的子组件引用,再修改子组件的响应式数据:

<script>
import ComboBox from '../components/ComboBox.vue';

export default {
    name: "Controls",
    components: {
        ComboBox,
    },
    created() {
        this.emitter.on('lock-combobox', (payload) => {
            // 通过payload.id获取目标子组件的ref
            const targetCombo = this.$refs[payload.id];
            if (targetCombo) {
                // 修改子组件的disabled响应式状态
                targetCombo.disabled = true;
            }
        });
    },
}
</script>

同时修正子组件中label的for属性绑定方式,原写法for={{selector_name}}存在语法错误,需改为:for="selector_name"以符合Vue的属性绑定规则。

内容的提问来源于stack exchange,提问作者Bilal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:10:23