父子组件,非父子组件通信

一、Vue官方文档说明

在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的。


prop 向下传递,事件向上传递

- - - - - - - - - - - - - - - - ✂- - - - - - - - - - - - - -✂-- - - - - - -- - - - - - - -✂- - - - - - -- - - - - - - - - -

二、父子组件消息传递示例

1.父组件传递数据给子组件

父组件数据如何传递给子组件呢?

使用 Prop 传递数据

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。

<parent>
  <child :child-msg="msg"></child> //这里必须要用 - 代替驼峰
</parent>

data(){
  return {
    msg: [1,2,3]
  };
}

子组件要显式地用 props 选项声明它预期的数据:

Vue.component('child', {
  // 声明 props
  props: ['childMsg'],
  // 就像 data 一样,prop 也可以在模板中使用
  // 同样也可以在 vm 实例中通过 this.childMsg 来使用
  template: '<span>{{ childMsg }}</span>'
})

PS: props 选项说明:

方式1:

props: ['childMsg']

方式2 :

props: {
  childMsg: Array // 这样可以指定传入的类型,如果类型不对,会警告
}

方式3:

props: {
  childMsg: {
    type: Array,
    default: [0,0,0] // 这样可以指定默认的值
  }
}

这样呢,就实现了父组件向子组件传递数据

2.子组件与父组件通信

那么,如果子组件想要改变数据呢?这在vue中是不允许的,因为vue只允许单向数据传递,这时候我们可以通过触发事件来通知父组件改变数据,从而达到改变子组件数据的目的.

2.1 子组件:

<template>
    <div @click="tellParent"></div>
</template>
methods: {
    tellParent() {
        this.$emit('toParent', 'Hi, father!'); // 主动触发toParent方法,'Hi, father!'为向父组件传递的数据
    }
}

 

2.2  父组件:

<parent>
    <child @toParent="change" :msg="msg"></child> // 监听子组件触发的toParent事件, 然后调用change方法
</parent>
methods: {
    change(msg) {
        this.msg = msg;
    }
}

 

3.非父子组件通信

如果2个组件不是父子组件那么如何通信呢?这时可以通过eventHub来实现通信. 所谓eventHub就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件.

3.1 在共有组件中,创建一个空的 Vue 实例作为事件中心:

let Hub = new Vue(); //创建事件中心

组件1:

<template>
    <a @click="event"></a>
</template>
methods: {
    event () {
        Hub.$emit('myEvent', 'Hi, there!'); // Hub触发事件自定义事件‘myEvent’,并传递信息“Hi, there!”
    }
}

组件2:

<template>
    <p>{{ message }}</p>
</template>
data() {
    return {
        message: '',
    }
},
created() {
    Hub.$on('myEvent', (msg) => { // Hub接收事件“myEvent”,并接受传递的信息msg
        this.message = msg;
    });
}

这样就实现了非父子组件之间的通信了.原理就是把Hub当作一个中转站!

3.2  在main.js(vue-cli脚手架创建的项目)中,给data添加一个 名字为Hub的空vue对象

这时候,在任何组件都可以调用事件发射 接受的方法了。

// 根组件(this.$root)
new Vue({
 el: '#app',
 router,
 render: h => h(App),
 data: {
  // 空的实例放到根组件下,所有的子组件都能调用
  Hub: new Vue()
 }
})

假设 B 组件里面有个按钮,点击按钮,把 123 传递给 A 组件

3.2.1 B组件内调用事件触发↓

<button @click="submit">提交<button>
 
methods: {
  submit() {
   // 通过this.$root.Hub获取此对象,再调用$emit方法
   this.$root.Hub.$emit('YOUR_EVENT_NAME', 123)
  }
}

A组件内调用事件接收↓

// 当前实例创建完成就监听这个事件
created(){
    this.$root.Hub.$on('YOUR_EVENT_NAME', (yourData) => {
        handle(yourData)
    })
},
 
methods: {
    handle(yourData) {
        console.log(yourData)
    }
},
 
// 在组件销毁时别忘了解除事件绑定
beforeDestroy() {
    this.$root.Hub.$off('YOUR_EVENT_NAME')
},

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值