非父子组件的传值

我们可以把网页拆分成很多个部分

首先是一个大的网页,然后上面是一个组件,左边也是一个组件,但是又可以拆分成2个组件,右边也是一个组件,但是也可以细分为3个组件

那么现在我想要父子组件传值可以通过:

父组件-子组件:通过props传值

子组件-父组件:通过事件触发传值

那么现在我想要第一层的组件和第三层的组件传值,如果用父子组件传值方法,那么就只能一层一层传,如果我现在想要右边的第三层组件和左边的第三层组件相互传值,也只能一层一层传递到第一层,然后再传递回来

这样做太过麻烦

那么我们可以使用 总线/Bus/发布订阅模式/观察者模式  来解决这个问题

现在想要实现的功能是当我点击Dell的时候,下面的Lee会变成Dell,点击Lee的时候,上面的Dell会变成Lee

首先是在Vue的protptype上挂载了一个名字叫做bus的属性,Vue.prototype.bus = new Vue(),这个属性指向一个Vue的实例,只要以后调用new Vue()或者创建组件的时候每一个组件上都会有一个bus属性,

既然我想要一个子组件在被点击的时候,另一个子组件的内容能够随之改变,那么先在div上写一个监听函数,<div @click="handleClick">{{content}}</div>

现在我想要往另一个组件上传递自己的信息

handleClick: function() {
                    this.bus.$emit('change', this.content);
}

this.bus 指的就是实例上挂载的bus,bus又是Vue上的实例,那么我们就可以通过¥emit这个属性来触发事件,同时携带了我们的数据,this.content

那么对于其他的组件来说,就要去监听这个change,怎么监听能,我们可以使用mounted这个生命周期钩子,也就是这个组件被挂载的时候会执行的函数

mounted: function() {
                this.bus.$on('change', function(msg) {
                    content = msg;
                });
     }

当然在写到这里的时候,

当你点击dell的时候会发现dell运行了两次

这是因为在一个child组件去触发事件的时候,两个child组件都进行了事件的监听,所以两个child都会显示这个msg

那么现在,只要我把this.content = msg 就可以了

点击完之后发现并没有什么改变,这是因为function(msg) {
                    this.content = msg;
                }

里面的this作用域发生了变化,

这样就可以了,再点击dell下面的lee就变成了dell

做完这些之后我们会发现控制台报错了

这是因为子组件的content是从父组件传过来的,但是我们却强行改变了其内容

this_.content = msg;

所以要改成下面这样子:

控制台也不会报错

<think>好的,我现在需要帮助用户了解在Vue3中如何实现非父子组件之间的,特别是关于事件总线和provide/inject方法。首先,我得回顾一下用户提供的引用内容,确保信息准确。 根据引用[1]和[2],Vue3中非父子组件通信可以使用provide/inject,以及全局事件总线mitt库。引用[3]提到使用复杂数据类型来保证响应式,这点需要注意。用户的问题明确提到了这两种方法,所以我需要详细说明这两种方法的具体实现步骤。 首先,provide/inject部分。在父组件中,使用provide选项提供数据,子组件通过inject选项接收。但要注意,默认情况下通过provide递的简单类型数据不是响应式的,需要使用响应式API如ref或reactive。例如,父组件用provide('data', reactive({...})),子组件用inject('data')来获取。这里需要强调响应式处理的重要性,避免用户遇到数据不更新的问题。 然后是全局事件总线。Vue3移除了内置的事件总线,推荐使用第三方库如mitt。需要演示如何创建事件总线实例,在组件中如何触发和监听事件。比如,在发送组件中用emitter.emit('event', data),在接收组件中用emitter.on('event', callback)。同时,要提醒用户在组件卸载时移除事件监听,防止内存泄漏。 接下来,用户可能的问题是如何选择这两种方法。provide/inject适合跨层级的数据共享,而事件总线更适合组件间的松散通信。需要比较两者的适用场景,帮助用户做出合适的选择。 另外,用户可能关心响应式数据的处理,所以需要详细说明如何结合Vue3的响应式API。例如,使用reactive或ref包裹数据,确保子组件能接收到响应式数据。引用[3]中的建议也需提及,优先使用复杂类型以保证响应式。 最后,生成相关问题需要考虑用户可能进一步的问题,比如两种方法的优缺点、响应式处理的具体方法、实际应用中的注意事项等。这些问题能帮助用户深入理解主题。 现在需要确保回答结构清晰,分步骤说明两种方法,并附上代码示例。同时,正确引用提供的资料,比如在提到provide/inject时引用[1][2][3],在事件总线部分引用[1]。注意检查代码语法是否正确,尤其是Vue3的组合式API语法,如setup函数和生命周期钩子的使用。</think>在Vue3中实现非父子组件通信,主要通过以下两种方法实现: ### 一、provide/inject 跨层级通信 1. **基础用法** 父组件使用$provide$提供数据,任意层级子组件通过$inject$注入数据: ```vue <!-- 父组件 --> <script setup> import { provide } from 'vue' provide('theme', 'dark') // 提供简单类型 provide('user', { name: '李华', age: 18 }) // 提供对象类型 </script> <!-- 子组件 --> <script setup> import { inject } from 'vue' const theme = inject('theme') const userInfo = inject('user') </script> ``` 2. **响应式处理** 需结合$ref$/$reactive$实现响应式数据更新[^3]: ```vue <!-- 父组件 --> <script setup> import { provide, reactive } from 'vue' const config = reactive({ theme: 'light' }) provide('config', config) </script> <!-- 子组件 --> <script setup> import { inject } from 'vue' const config = inject('config') const toggleTheme = () => config.theme = config.theme === 'light' ? 'dark' : 'light' </script> ``` ### 二、全局事件总线 使用mitt库实现组件间事件通信[^1]: ```javascript // eventBus.js import mitt from 'mitt' export const emitter = mitt() // 发送组件 import { emitter } from './eventBus' emitter.emit('formSubmit', { data: '提交内容' }) // 接收组件 import { onUnmounted } from 'vue' import { emitter } from './eventBus' emitter.on('formSubmit', handleSubmit) onUnmounted(() => emitter.off('formSubmit', handleSubmit)) ``` ### 方法对比 | 方法 | 适用场景 | 特点 | |---------------|-------------------------|-----------------------------| | provide/inject | 跨层级数据共享 | 适合主题/配置等静态数据递 | | 事件总线 | 任意组件间事件通信 | 适合触发动作类通信,需注意事件解注册 | 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值