Vue中组件的通信方式有哪些?

本文详细介绍了Vue中组件间的多种通信方式,包括props、$emit、ref、EventBus、$parent/$children、$attrs/$listeners以及Provide/Inject和Vuex。通过实例解析了各种通信方式的适用场景、实现方法和注意事项,帮助开发者更好地理解和应用Vue组件通信。

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

一、组件间通信的分类

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件间之间的通信

二、组件间通信的方案

  1. 通过 props 传递
  2. 通过 $emit 触发自定义事件
  3. 使用 ref
  4. EventBus
  5. $parent 或$root
  6. attrs 与 listeners
  7. Provide 与 Inject
  8. Vuex

1、props传递数据

适用场景:父组件向子组件传值

Child.vue:

props:{  
    // 字符串形式  
 name:String // 接收的类型参数  
    // 对象形式  
    age:{    
        type:Number, // 接收的类型为数值  
        defaule:18,  // 默认值为18  
       require:true // age属性必须传递  
    }  
}  

Father.vue

<Child name="jack" age=18 />  

2、$emit触发自定义事件

适用场景:子组件传递数据给父组件。

在子组件中使用this.$emit(),第一个参数为自定义事件名,第二个参数为传递的数据。

<template>
  <div class="home">
    <h1>我是子组件</h1>
    <h2 @click="change('武汉')">测试其emit组件</h2>
  </div>
</template>

<script>
// @ is an alias to /src
export default {
  methods: {
    change(val) {
      let data = {
        msg: val,
      };
      this.$emit("showCityName", data);
    },
  },
};
</script>

在父组件中,在子组件的标签上绑定method,接收传递过来的参数。

<template>
  <div class="hello">
    <h2>我是父组件,我需要建立一些参数</h2>
    <h3>我所在地的名称是:{{ msg }}</h3>
    <span><mHome @showCityName="updateCityName" /></span>
  </div>
</template>

<script>
import mHome from "@/views/Home.vue";
export default {
  components: {
    mHome,
  },
  data() {
    return {
      msg: "北京",
    };
  },
  methods: {
    updateCityName(data) {
      this.msg = data.msg;
    },
  },
};
</script>

ref

在子组件的标签上加上ref,就可以通过$ref获取子组件。

<Children ref="foo" />  
  
this.$refs.foo.xxx  // 获取子组件实例,通过子组件实例我们就能拿到对应的数据,xxx为子组件中的data  

 此外,ref还可以用来获取页面的dom元素和调用子组件中的方法。

EventBus

  • 使用场景:兄弟组件传值
  • 创建一个中央时间总线EventBus
  • 兄弟组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
  • 另一个兄弟组件通过$on监听自定义事件

初始化

//main.js
//方式一
Vue.prototype.$eventBus = new Vue();
//方式二
window.eventBus = new Vue();

触发事件

//使用方式一定义时
this.$eventBus.$emit('eventName', param1,param2,...)
//使用方式二定义时
eventBus.$emit('eventName', param1,param2,...)

监听事件

//使用方式一定义时
this.$eventBus.$on('eventName', (param1,param2,...)=>{
    //需要执行的代码
})
//使用方式二定义时
eventBus.$on('eventName', (param1,param2,...)=>{
    //需要执行的代码
})

移除事件

//使用方式一定义时
this.$eventBus.$off('eventName');
//使用方式二定义时
eventBus.$off('eventName');

$parent 或$ children

$parent可以获取父组件中的元素。

        父组件

<template>
  <div>
    <h1>父组件</h1>
    <h-child></h-child>
  </div>
</template>
<script>
  // 引入子组件
  import HChild from './Child'
  export default {
    name: 'Parent',
    components: {
      HChild
    },
    data () {
      return {
        msg: 'data from parent'
      }
    },
    methods: {
      fun () {
        console.log('parent fun')
      }
    }
  }
</script>

        子组件

<template>
  <div>
    <h1>子组件</h1>
    <button @click="showParent">调用父组件的数据和方法</button>
  </div>
</template>
<script>
  export default {
    name: 'Child',
    methods: {
      showParent () {
        // 获取到所有的子组件
        console.log(this.$parent)
        // 获取指定子组件中的指定数据
        console.log(this.$parent.msg)
        // 调用子组件的方法
        this.$parent.fun()
      }
    }
  }
</script>

此外,通过共同父辈$parent可以建立兄弟组件之间的通信。(类似eventBus)

兄弟组件A:

this.$parent.on('add',this.add)

兄弟组件B:

this.$parent.emit('add')

$children可以获取子组件的数组,再获取其中的元素。

        子组件

<template>
  <div>
    <h1>子组件</h1>
  </div>
</template>
<script>
  export default {
    name: 'Child',
    data () {
      return {
        msg: 'msg from child'
      }
    },
    methods: {
      fun () {
        console.log('child fun')
      }
    }
  }
</script>

        父组件

<template>
  <div>
    <h1>父组件</h1>
    <h-child></h-child>
  </div>
</template>
<script>
  // 引入子组件
  import HChild from './Child'
  export default {
    name: 'Parent',
    components: {
      HChild
    },
    mounted () {
      // 获取到所有的子组件,结果是一个数组
      console.log(this.$children)
      // 获取指定子组件中的指定数据
      console.log(this.$children[0].msg)
      // 调用子组件的方法
      this.$children[0].fun()
    }
  }
</script>

$attrs 与$listeners

  • 适用场景:祖先传递数据给子孙
  • 设置批量向下传属性$attrs和 $listeners
  • 包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。
  • 可以通过 v-bind="$attrs" 传⼊内部组件

$attrs包含了父组件传入的且没有在props中传入的数据,如果某一属性存在于props中,则会在$attrs中被移除。

// 父组件
<child-com class="com" name="attr" :foo="foo" :boo="boo" :coo="coo" :doo="doo" @click="test"></child-com>
...
data() {
  return {
    foo: 'Hello World!',
    boo: 'Hello Javascript!',
    coo: 'Hello Vue',
    doo: 'Last'
  }
},
...

// child-com.vue
 export default {
  name: 'childCom',
  components: {
    childCom2
  },
  created() {
    console.log(this.$attrs) // {name: "attr", foo: "Hello World!", boo: "Hello Javascript!", coo: "Hello Vue", doo: "Last"}
  }
}

provide 与 inject

  • 在祖先组件定义provide属性,返回传递的值
  • 在后代组件通过inject接收组件传递过来的值

祖先组件

provide(){  
    return {  
        foo:'foo'  
    }  
}  

后代组件

inject:['foo'] // 获取到祖先组件传递过来的值  

vuex

适用于复杂关系的组件数据传递,类似于redux。

  • state用来存放共享变量的地方

  • getter,可以增加一个getter派生状态,(相当于store中的计算属性),用来获得共享变量的值

  • mutations用来存放修改state的方法。

  • actions也是用来存放修改state的方法,不过action是在mutations的基础上进行。常用来做一些异步操作

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值