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

Vue.js如何在三个无父子关联的组件间传值实现待办项添加功能?

解决方案

不需要引入Vuex,也不需要合并组件,使用Vue内置的跨组件通信方案即可实现需求,以下是Vue2和Vue3两个版本的实现方式:

Vue2 实现方案(用事件总线)

事件总线是Vue2原生支持的轻量级跨组件通信方式,无需引入额外依赖。

步骤1:全局注册事件总线

在项目入口文件main.js中添加如下代码:

import Vue from 'vue'
// 新增这一行,挂载全局事件总线
Vue.prototype.$bus = new Vue()
// 原有其他代码...
new Vue({
  render: h => h(App)
}).$mount('#app')

步骤2:修正各组件代码

1. 表单组件 TodoTemplate

修正错误的props写法,移除重复的value绑定,监听添加按钮的提交事件,触发时传递当前填写的待办数据:

<template>
    <div ref="template" class="task-template">
        <div class="task-template__wrapper">
            <div class="task-template__input">
                <input v-model="todo.header" ref="header" class="task-template__header" type="text" placeholder="Название задачи">
            </div>
            <div class="task-template__input">
                <input v-model="todo.description" ref="description" class="task-template__description" type="text" placeholder="Описание">
            </div>
        </div>
        <div class="task-template__actions">
            <div class="task-template__actions_inner">
                <inline-svg class="task-template__btn hover" alt="Подзадачи"
                            :src="getImageUrl(`bulleted-list.svg`)"></inline-svg>
                <inline-svg class="task-template__btn" alt="Добавить в группу"
                            :src="getImageUrl(`folder.svg`)"></inline-svg>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "TodoTemplate",
    props: {
        initTodo: {
            type: Object,
            // 对象类型默认值必须用工厂函数返回
            default: () => ({
                header: "",
                description: "",
                tasks: [],
                groups: []
            })
        }
    },
    data() {
        return {
            todo: {...this.initTodo}
        }
    },
    created() {
        // 监听添加按钮的提交事件
        this.$bus.$on('trigger-submit-todo', () => {
            // 把当前填写的待办数据传给列表组件
            this.$bus.$emit('submit-todo', this.todo)
            // 提交后清空表单
            this.todo = {header: '', description: '', tasks: [], groups: []}
        })
    },
    beforeDestroy() {
        // 组件销毁前移除事件监听,避免内存泄漏
        this.$bus.$off('trigger-submit-todo')
    }
}
</script>

2. 添加按钮组件 CreateTodo

修正this指向错误,点击时发射提交触发事件:

<template>
    <div class="add-button" @click="submit">
        <div class="add-button__container">
            Добавить задачу
        </div>
    </div>
</template>

<script>
export default {
    name: "CreateTodo",
    methods: {
        // 不要用箭头函数,否则this指向不对
        submit() {
            this.$bus.$emit("trigger-submit-todo")
        }
    }
}
</script>

3. 待办列表组件 TodoList

监听待办提交事件,调用新增方法,修正v-for的key值错误:

<template>
    <section>
        <!-- 给表单组件绑定初始空todo -->
        <TodoTemplate :init-todo="newTodo" />
        <ul class="todo">
            <TodoItem v-for="todo in todos" :title="todo.header" :key="todo.header" />
        </ul>
    </section>
</template>

<script>
import TodoTemplate from "@/components/TodoTemplate/TodoTemplate";
import TodoItem from "@/components/TodoItem/TodoItem";

export default {
    name: "TodoList",
    components: {TodoItem, TodoTemplate},
    data() {
        return {
            newTodo: {
                header: "",
                description: "",
                tasks: [],
                groups: []
            },
            todos: [
                {
                    header: '🍾  Купить шампанское',
                    description: '"Dom Perignon", Rose Vintage 2003 Brut',
                    tasks: [],
                    groups: []
                }
            ]
        }
    },
    created() {
        // 监听表单提交的待办数据
        this.$bus.$on('submit-todo', (todo) => {
            this.addTodo(todo)
        })
    },
    beforeDestroy() {
        this.$bus.$off('submit-todo')
    },
    methods: {
        addTodo(todo) {
            // 深拷贝避免引用问题
            this.todos.push(JSON.parse(JSON.stringify(todo)))
        }
    }
}
</script>

Vue3 实现方案(用 provide/inject)

Vue3移除了事件总线,无需引入mitt的情况下可以用原生的provide/inject实现全局状态共享,在根组件App.vue提供共享的待办列表和新增方法,所有组件都可以注入调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 08:51:01