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

Vue组件插槽能否用v-bind?Vuetify菜单绑定报错求解决方案

解决Vuetify菜单组件插槽绑定activator的TypeError问题

先说说问题出在哪:

  • 父组件里直接写this.$refs.miniProfile(uuid)是错误的,要调用组件暴露的open方法才对
  • 把activator直接绑定到<slot>标签上不可行,slot不是真实DOM元素,得把activator包含的事件和属性传递给插槽内的具体元素使用

下面是修正后的完整可运行代码:

可复用迷你资料菜单组件(MiniProfileMenu.vue)

<template>
    <v-menu
        v-model="menu"
        :close-on-content-click="false"
        location="end"
    >
        <template v-slot:activator="{ on, attrs }">
            <!-- 将菜单激活所需的事件、属性传递给插槽,由内部元素绑定 -->
            <slot v-bind="{ on, attrs }" />
        </template>
        <v-card class="profile-card">
            <v-row align="center">
                <v-col cols="auto" style="width: 64px">
                    <!-- 通过props接收用户头像,支持动态渲染 -->
                    <v-img :src="user?.avatar" alt="用户头像" width="64" height="64" rounded />
                </v-col>
                <v-col>
                    <h4 class="mb-1">{{ user?.name || '匿名用户' }}</h4>
                    <p class="text-grey-darken-1 text-sm">{{ user?.desc || '暂无个人描述' }}</p>
                </v-col>
            </v-row>
            <!-- 可添加菜单操作选项 -->
            <v-divider class="my-2"></v-divider>
            <v-list dense>
                <v-list-item @click="close">
                    <v-list-item-icon>
                        <v-icon>mdi-logout</v-icon>
                    </v-list-item-icon>
                    <v-list-item-title>退出登录</v-list-item-title>
                </v-list-item>
            </v-list>
        </v-card>
    </v-menu>
</template>

<script>
export default {
    name: "MiniProfileMenu",
    // 接收用户信息,让组件支持动态渲染不同用户数据
    props: {
        user: {
            type: Object,
            default: () => ({})
        }
    },
    data() {
        return {
            menu: false
        };
    },
    methods: {
        open() {
            this.menu = true;
        },
        close() {
            this.menu = false;
        }
    }
};
</script>

<style scoped>
.profile-card {
    width: 100%;
    min-width: 280px;
}
</style>

页面调用示例(DashboardCommunityPage.vue)

<template>
    <v-container>
        <v-row>
            <v-spacer />
            <v-col cols="auto">
                <mini-profile-menu 
                    ref="miniProfile"
                    :user="currentUser"
                >
                    <!-- 将插槽传递的on事件、attrs属性绑定到div上,菜单会关联该元素 -->
                    <div v-on="on" v-bind="attrs" class="pa-2 cursor-pointer">
                        点击打开我的资料
                    </div>
                </mini-profile-menu>
            </v-col>
            <v-spacer />
        </v-row>
    </v-container>
</template>

<script>
import MiniProfileMenu from "#/components/MiniProfileMenu.vue";

export default {
    name: "DashboardCommunityPage",
    components: { MiniProfileMenu },
    data() {
        return {
            // 示例用户数据,实际可从接口获取
            currentUser: {
                name: "张三",
                desc: "前端开发工程师",
                avatar: "https://via.placeholder.com/64"
            },
            user_uuid: "123456"
        };
    },
    methods: {
        // 如需手动触发菜单打开,调用此方法即可
        openMiniProfile() {
            this.$refs.miniProfile.open();
        }
    }
};
</script>

核心修改说明

  1. 拆分activator属性:把v-menu的activator拆分为on(事件集合)和attrs(HTML属性)传递给插槽,让内部div元素绑定这些内容,确保菜单能正确关联到点击的DOM元素,避免null引用错误
  2. 组件Props化:通过user props接收用户数据,使组件可以在不同页面传递不同用户信息,提升复用性
  3. 修正方法调用:原代码直接调用ref对象的方式错误,改为调用组件的open方法;同时绑定on事件后,点击div会自动触发菜单打开
  4. 移除冗余变量:删除原组件中无用的activator变量,简化代码逻辑

修改完成后,点击div元素时菜单会精准显示在元素旁,不会再出现TypeError: Cannot read properties of null (reading 'key')错误,组件也能在各页面灵活复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:50:37