Vue中组件之间的传值

先简单说一下Vue中的组件,Vue中的组件为了能够在模板中使用,必须要先注册以便Vue能够识别到这个组件.组件注册分为两种类型:全局注册和局部注册.

有了组件,就会有或者涉及到组件之间的传值.总的来说,Vue组件之间的传值,主要分为3种类型或情况下的传值:

  1. 简单的父子组件之间的传值
  2. 同属于同一个父组件之间兄弟组件之间的传值
  3. 好不相关的组件之间的传值

简单的父子组件传值和同属于同一个父组件的兄弟组件之间的传值,Vue提供了方法可以直接进行传值,不需要Vuex.

简单父子组件之间的传值

为了看起来简单,文中的demo都写的非常简单,就是为了看起来简单,就是篇幅长了些.

父组件向子组件传值

父组件cmp.vue

<template>
    <div class="parent">
        {{msg}}
        <ComponentChild :parentToChildData="parentData"></ComponentChild>
    </div>
</template>

<script>
import ComponentChild from './cmpc'
export default {
    name:"componentP",
    components:{
        ComponentChild
    },
    data() {
        return {
            msg:"Hello, ComponentP",
            parentData:"我是来自父组件的数据"
        }
    }
}
</script>

子组件cmpc .vue

<template>
    <div class="componentA">
        <div>{{parentToChildData}}</div>
        <div>{{msg}}</div>
    </div>
</template>
<script>
export default {
    name:"componentA",
    data() {
        return {
            msg: "我是子组件的数据"
        }
    },
    props:["parentToChildData"]
}
</script>

我们先看父组件文件cmp.vue.

父组件中引入并注册了子组件ComponentChild,并通过props的方式向子组件传递了一个值:parentToChildData.然后子组件通过props方式接收到了从父组件传递过来的值.页面数据的渲染效果如下:

子组件向父组件传值

父组件cmp.vue

<template>
    <div class="parent">
        <p>{{msg}}</p>
        <p>{{data1}}</p>
        <!--
            @dataFromParent:父组件中定一的事件,可以简单的理解为就是和click、hover一样的事件,只不过不是内置的事件类型,而是一个自定义的事件名称;目的:在子组件中调用该方法,实现从子组件向父组件的值的传递
            dataFromChildToParent:事件响应函数,会在当前的组件中有具体实现
        -->
        <ComponentChild :parentToChildData="parentData" @dataFromParent="dataFromChildToParent"></ComponentChild>
    </div>
</template>

<script>
import ComponentChild from './cmpc'
export default {
    name:"componentP",
    components:{
        ComponentChild
    },
    data() {
        return {
            msg:"Hello, ComponentP",
            parentData:"我是来自父组件的数据",
            data1:""
        }
    },
    methods: {
        dataFromChildToParent(data){ //从子组件传递过来的数据
            this.data1 = data;
        }
    },
}
</script>

子组件cmpc.vue

<template>
    <div class="componentA">
        <h3>我是子组件</h3>
        <div>{{parentToChildData}}</div>
        <div>{{msg}}</div>
        <button @click="dataToParent">向父组件传递数据</button>

    </div>
</template>
<script>
export default {
    name:"componentA",
    data() {
        return {
            msg: "我是子组件的数据",
            childFromData:"新来的子组件数据"
        }
    },
    props:["parentToChildData"],
    methods: {
        dataToParent(){
            this.$emit("dataFromParent",this.childFromData);//dataFromParent:父组件中的方法;this.childFromData这个参数为子组件要向父组件传递的数据
        }
    },
}
</script>

这里就不演示效果了,如果有读者比较期待效果,可以直接将上面的代码复制到自己的项目中,然后建个路由就可以看效果了.

父组件通过props向子组件传递数据.我们需要注意,组件中数据共有3种形式的数据,即组件模板中的数据的来源有3个:data、props、computed.

data:就是组件初始化时的data函数了;

props:父组件传递过来的数据

compoted:模板中一些数据的展示依赖于data中一些属性的变化自动计算的值,来源时通过compoted计算的来的,本质上还是data.

对于这3点解释,是个人的一点见解,没有什么官方的说法,这就仁者见仁智者见智了.看怎么好理解就怎么理解了.

这个时候我们也许会想,我们直不把子组件中的数据上传给父组件了,而直接把子组件中的数据渲染到页面元素中不也可以吗?因为我把数据传递给了父组件,父组件也是会再通过props将这些数据通过子组件的元素来展示.从道理上来说是可以直接将自元素的新数据不传递给父组件,而仅在子组件本身处理这些数据,但这里又会涉及到一个问题,就是数据的整合问题,包括数据的遍历、循环等,会把数据的处理搞的很复杂,不如直接将子组件数据传递给父组件再通过props传递回来处理简单.

同属于一个父组件的兄弟节点之间的传值

其实这个比较好理解,及时在一个模板文件中,同时引用了多个子组件,那么这子组件中的一个有数值的变化了,其他子组件也会有相关的值的变化.这里并没有技术难点,就是把前面我们介绍过的父子组件之间的传值综合利用了起来.先将子组件A的值传递给父组件,然后父组件再通过props将从组件A获取到的数据传递给子组件B,这样实现了兄弟组件之间值的传递.

看个例子:

父组件componentP.vue

<template>
    <div>
        <div class="cmp1">
            {{msg}}
            <ComponentA @cmpAToParent="cmpASendDataToParent" :cmaData="cmadata"></ComponentA>
        </div>
        <div class="cmp2">
            <ComponentB :msgfromP="msg"></ComponentB>
        </div>
    </div>
</template>

<script>
import ComponentA from './componentA'
import ComponentB from './componentB'
export default {
    name: "ComponentBrother",
    data() {
        return {
            msg:"",
            cmadata:"父组件传递给组件A测试数据"
        }
    },
    components: {
        ComponentA, ComponentB
    },
    methods: {
        cmpASendDataToParent(data) {
            this.msg = data;
        }
    },
}
</script>

子组件A:componentA.vue

<template>
    <div class="cmp-a">
        <p>{{msg}}</p>
        <p>{{cmaData}}</p>
        <input type="text" class="ipt" v-model="username">
        <button class="btn" @click="comASendDataToParent">组件A向父组件传递数据</button>
    </div>
</template>
<script>
export default {
    name:'ComponentA',
    data(){
        return {
            msg:"组件A",
            username:""
        }
    },
    props:["cmaData"],
    methods: {
        comASendDataToParent(){
            this.$emit("cmpAToParent",this.username);
        }
    },
}
</script>

子组件B:componentB.vue

<template>
    <div>
        <p>{{msg}}</p>
        <p>A组件的变化,引起的B的变化:{{msgfromP}}</p>
        <button class="btn" @click="sentDataToParent">sendDataToParent</button>
    </div>
</template>

<script>
export default {
    name:'ComponentB',
    data(){
        return {
            msg:"组件B"
        }
    },
    props:["msgfromP"],
    methods: {
        sentDataToParent(){
            console.log("组件B中点击一下按钮");
        }
    },
}
</script>

demo中只实现了子组件A向子组件B的传值,没有做子组件B向子组件A传值的实现,道理是一样的.

兄弟节点之间的传值,除了上面的先子组件传递给父组件然后父组件再传递给子组件外,还有另外一种通过程序化的事件侦听器(也叫中央事件总线)来监听.

到此为止,有规律的组件之间的传值已经介绍完了,还有一种无规定关系组件之间的传值了.这种关系的组件之间的传值就不能通过上面介绍的方式来实现了,可以借助vuex来实现.

不相关组件之间的值的传递

 

<think>好的,用户想了解在Vue中如何实现兄弟组件之间方法。我需要先回忆一下Vue3中兄弟组件通信的几种方式。根据之前提供的引用,主要有两种方法:使用Mitt插件或者利用provide和inject的响应式API。另外,还有通过事件总线(Bus)的方式,不过这在Vue3中可能需要自己实现,或者使用第三方库如Mitt。 首先,用户可能已经了解过Vue2中的事件总线,但在Vue3中,官方移除了$on等方法,所以需要替代方案。Mitt是一个轻量的事件总线库,适用于Vue3。步骤包括安装Mitt,创建事件总线实例,然后在兄弟组件中分别使用emit和on来触发和监听事件。需要确保两个组件引用的是同一个事件总线实例,通常会在全局注册。 另一种方法是使用provide和inject配合响应式数据。父组件提供一个响应式的对象,兄弟组件通过inject获取这个对象,并修改其中的数据。这样,当数据变化时,所有注入该数据的组件都会更新。需要注意的是,Vue3的provide/inject默认不是响应式的,所以必须使用ref或reactive来包装数据。 用户可能关心哪种方法更推荐。Mitt适合事件驱动的通信,而provide/inject适合共享状态。如果项目已经使用Pinia或Vuex,可能更推荐状态管理库来处理兄弟组件通信,但用户的问题没有提到这些,所以暂时不引入。 另外,引用中的示例代码显示在子组件中使用$emit,但Vue3中兄弟组件不能直接通过父组件递事件,需要父组件作为中介,或者使用事件总线。所以需要区分子组件和兄弟组件的场景。 需要确保回答结构清晰,分点说明每种方法,并给出示例代码。同时,根据用户提供的引用,正确引用来源,比如Mitt方法引用[^1],事件总线引用[^3],而引用[^2]中的例子可能不适用于兄弟组件,因为$emit需要父组件监听,所以可能需要指出那种方式适用于父子而非兄弟,避免混淆。 最后,生成相关问题,比如性能比较、其他方法如Vuex,或者具体使用场景,帮助用户深入理解。</think>在 Vue3 中实现兄弟组件通信的常用方法主要有以下两种方式,均支持响应式数据递: --- ### 一、使用 Mitt 事件总线(推荐) 1. **安装 Mitt 插件** ```bash npm install mitt ``` 2. **创建全局事件总线** ```javascript // src/utils/bus.js import mitt from 'mitt' export default mitt() ``` 3. **组件 A 发送事件** ```vue <script setup> import bus from '@/utils/bus' const sendData = () => { bus.emit('customEvent', { value: '数据内容' }) } </script> ``` 4. **组件 B 接收事件** ```vue <script setup> import bus from '@/utils/bus' import { onMounted } from 'vue' onMounted(() => { bus.on('customEvent', (data) => { console.log('接收数据:', data.value) // 输出:数据内容 }) }) </script> ``` **特点**:解耦组件关系,适合跨层级通信[^1][^3] --- ### 二、使用 provide/inject + 响应式状态 1. **父组件提供共享状态** ```vue <script setup> import { provide, reactive } from 'vue' const sharedState = reactive({ message: '' }) provide('sharedKey', sharedState) </script> <template> <ComponentA /> <ComponentB /> </template> ``` 2. **兄弟组件修改状态** ```vue <!-- ComponentA --> <script setup> import { inject } from 'vue' const state = inject('sharedKey') state.message = '来自A的数据' </script> ``` 3. **兄弟组件读取状态** ```vue <!-- ComponentB --> <script setup> import { inject } from 'vue' const state = inject('sharedKey') console.log(state.message) // 输出:来自A的数据 </script> ``` **特点**:适合需要持久化共享的状态[^1] --- ### 性能对比 | 方法 | 适用场景 | 数据流向 | |-----------|----------------------|------------| | Mitt | 瞬时事件通信(表单提交/通知) | 单向/双向 | | provide | 需要长期维护的共享状态(主题/配置) | 集中式状态管理 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值