Vue组件通信

本文深入探讨了Vue组件之间的三种通信方式:父子组件、兄弟组件和嵌套多层组件的通信机制。详细介绍了如何利用props、$emit、bus和attrs/listeners进行数据传递和事件触发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vue组件的关系分为3种:
1.父子组件
2.兄弟组件
3.嵌套多层的组件

A父子组件
父组件:用:age的方式把age传给子组件,用v-on的方式租接收子组件传来的参数

<template>
    <div class="father">
       <Child :age='age' v-on:addAge='addAge'/>    
    </div>
</template>
<script>
import Child from './child.vue'
export default {
    name:'father',
    data(){
        return{
          age:'18'
        }
    },
    methods:{
        addAge(v){
            console.log(v)
        }
    },
    components:{Child}
}
</script>

子组件:用props去接收父组件传下来的参数,用this.$emit(key,value)的方式将子组件的信息传给父组件

<template>
    <div class="child">
       年龄是{{age}}
       <p @click="addAge">增加年龄</p>
    </div>
</template>
<script>
export default {
    name:'child',
    props:['age'],
    methods:{
       addAge(){
           this.$emit('addAge','19')
       }
    }
}
</script>

B兄弟组件
兄弟组件的通信需要借助一个中转站bus;
bus.js中主要是实例化vue

import Vue from 'vue'
export default new Vue;

父组件:

<template>
    <div class="father">
       <Brother1/>
       <Brother2/>  
    </div>
</template>
<script>
import Brother1 from './brother1.vue'
import Brother2 from './brother2.vue'
export default {
    name:'father',
    components:{Brother1,Brother2}
}
</script>

兄弟1组件:手动点击事件,将值传给兄弟2组件,通过引入bus,使用bus.$emit方法

<template>
    <div class="child">
      <p @click="handleClick">点击</p>
    </div>
</template>
<script>
import Bus from './bus.js'
export default {
    data(){
        return{
           age:'18'
        }
    },
    name:'brother1',
    methods:{
       handleClick(){
           Bus.$emit('age',this.age)
       }
    }
}
</script>

兄弟2组件:通过引入bus,使用bus,$on去接收

<template>
    <div class="child">
       年龄是{{age}}
    </div>
</template>
<script>
import Bus from './bus.js'
export default {
    name:'brother2',
    data(){
        return{
            age:null
        }
    },
 mounted(){
     this.$nextTick(function(){
         Bus.$on('age',(v)=>{
             this.age=v
         })
     })
 }
}
</script>

C嵌套多层的组件
在vue2.4以前,有2种方法可处理:
①通过父子组件层层往下级传
②使用vuex,统一管理数据
这里介绍vue2.4的一个方法,attrs及attrs及attrslisteners,面试中经常会被问到这个方法,一定要掌握。

父组件:

<template>
    <div class="father">
       <child
         :age='age'
         :sex='sex'
         v-on:grandsonParame='grandsonParame'
       />
    </div>
</template>
<script>
import child from './child.vue'
export default {
    name:'father',
    data(){
        return{
            age:'18',
            sex:'男'
        }
    },
    methods:{
        grandsonParame(v){
            console.log(`grandsonParame is ${v}`)
        }
    },
    components:{child}
}
</script>

子组件:

<template>
    <div class="child">
      <Grandson v-bind="$attrs" v-on="$listeners"/> 
      <!-- 
      用 v-bind="$attrs"的格式将父组件中所有往下传的参数传给自己的子组件 但不包含:class
      用v-on="$listeners"的格式去接收自己子组件传给父组件的值
      -->
    </div>
</template>
<script>
import Grandson from './grandson.vue'
export default {
    name:'child',
    components:{Grandson}
}
</script>

孙组件:直接去取attrs得值,里面包含第一级组件传的所有参数,并且通过this.attrs得值,里面包含第一级组件传的所有参数,并且通过this.attrsthis.emit的方式把把当前位置的参数传给第一级组件,

<template>
    <div class="grandson">
      age:{{$attrs.age}}
      sex:{{$attrs.sex}}
      <p @click="handleClick">点击</p>
    </div>
</template>
<script>
export default {
    name:'grandson',
    methods:{
        handleClick(){
            this.$emit('grandsonParame','come from grandson')
        }
    }
}
</script>
### Vue 组件间的通信方法 Vue 提供了多种组件通信的方式,适用于不同的场景和需求。以下是常见的 Vue 组件通信方法及其实现技巧: #### 1. **Props 和 $emit** `props` 是父组件向子组件传递数据的主要方式,而 `$emit` 则用于子组件向父组件发送事件通知。 - 父组件通过 `props` 将数据传递到子组件中[^1]。 - 子组件可以通过调用 `$emit` 方法触发自定义事件,并将数据回传给父组件[^2]。 示例代码如下: ```vue <!-- ParentComponent.vue --> <template> <ChildComponent :message="parentMessage" @childEvent="handleChildEvent" /> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from Parent', }; }, methods: { handleChildEvent(data) { console.log('Data received from child:', data); } } }; </script> ``` ```vue <!-- ChildComponent.vue --> <template> <div>{{ message }}</div> </template> <script> export default { props: ['message'], mounted() { this.$emit('childEvent', 'Hello from Child'); } }; </script> ``` --- #### 2. **Provide 和 Inject** `provide/inject` 主要用于跨多层嵌套的父子组件之间共享状态,适合全局配置或深层嵌套的情况。 示例代码如下: ```javascript // ParentComponent.vue export default { provide() { return { sharedState: this.sharedState, }; }, data() { return { sharedState: 'Shared Data', }; }, }; // DeeplyNestedChildComponent.vue export default { inject: ['sharedState'], created() { console.log(this.sharedState); // 输出 "Shared Data" }, }; ``` --- #### 3. **v-model (双向绑定)** `v-model` 实现了父子组件之间的双向绑定,通常用于表单输入控件。 示例代码如下: ```vue <!-- ParentComponent.vue --> <template> <CustomInput v-model="inputValue" /> </template> <script> import CustomInput from './CustomInput.vue'; export default { components: { CustomInput }, data() { return { inputValue: '', }; }, }; </script> ``` ```vue <!-- CustomInput.vue --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script> export default { props: ['modelValue'], }; </script> ``` --- #### 4. **Vuex (集中式状态管理)** 对于复杂的大型项目,推荐使用 Vuex 来统一管理和分发状态。 示例代码如下: ```javascript // store.js import { createStore } from 'vuex'; const store = createStore({ state: { count: 0, }, mutations: { increment(state) { state.count++; }, }, }); export default store; ``` ```vue <!-- AnyComponent.vue --> <template> <button @click="increment">Increment Count</button> {{ count }} </template> <script> export default { computed: { count() { return this.$store.state.count; }, }, methods: { increment() { this.$store.commit('increment'); }, }, }; </script> ``` --- #### 5. **Mitt 或 Event Bus** 如果不想引入 Vuex,可以使用轻量级库 Mitt 创建一个简单的事件总线来处理非父子关系的组件通信。 示例代码如下: ```javascript // eventBus.js import mitt from 'mitt'; const emitter = mitt(); export default emitter; // ComponentA.vue emitter.emit('custom-event', payload); // ComponentB.vue emitter.on('custom-event', handlerFunction); ``` --- #### 6. **Expose/Ref** 在组合式 API 中,`ref` 可以用来访问子组件实例中的公开属性或方法,配合 `defineExpose` 使用。 示例代码如下: ```vue <!-- ParentComponent.vue --> <template> <ChildComponent ref="childRef" /> </template> <script setup> import { ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; const childRef = ref(null); function callChildMethod() { childRef.value?.publicMethod(); } </script> ``` ```vue <!-- ChildComponent.vue --> <script setup> defineExpose({ publicMethod() {}, }); </script> ``` --- #### 7. **Attrs 和 Listeners** 当某些属性未被声明为 `props` 时,它们会自动成为 `attrs` 并向下传播;类似的还有 `$listeners`,不过在 Vue 3 中已被移除并替换为 `v-on`。 示例代码如下: ```vue <!-- GrandParentComponent.vue --> <template> <ParentComponent customAttr="test" @customEvent="handleCustomEvent" /> </template> ``` ```vue <!-- ParentComponent.vue --> <template> <ChildComponent v-bind="$attrs" v-on="$listeners" /> </template> <script> export default { inheritAttrs: false, // 防止 attrs 被挂载到根节点上 }; </script> ``` --- #### 总结 以上列举了几种主流的 Vue 组件通信方式,每种都有其适用范围和特点。开发者应根据具体业务需求选择合适的方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值