Vue组件间通信

115 阅读2分钟

父子之间通信

props

子组件设置 props 来接收父组件传来的值/方法。

// mother组件

//将 name 和sayHi()传给 daughter
<my-daughter :name="name" :sayHi="sayHi"></my-daughter>

data() {
    return {
        name: 'cloud',
    }
    },
methods: {
    sayHi() {
        console.log('hi');
    },
    },
//daughter组件
<span> mother传来的name:{{ name }}</span>  
<button @click="sayHi">mother传来的方法</button> 

//接收mother传来的数据和方法并定义类型
props: {
    name: {
        type: String
    },
    sayHi: {
        type: Function
    }
    },

emit

子组件通过emit传递方法的方式传递数据给父组件。

//mother组件

//接收daughter传来的方法
<my-daughter @changeAge="changeAge"></my-daughter>
<span>mother组件的年龄:{{ age }}</span>

data() {
    return {
        age: 18
    }
},
methods: {
    // 参数为daughter传来的
    changeAge(age) {
        this.age = age;
    }
}
//daughter组件

//通过daughter自身定义的事件来触发传给mother的自定义事件
<button @click="emitAge">传给mother的修改年龄</button>

data() {
    return {
        age: 50,
    }
},
 methods: {
    emitAge() {
        // 传递一个自定义事件给mother组件,并携带要传递过去的参数
        this.$emit('changeAge', this.age)
}

ref && refs

父组件可以通过在使用的子组件上添加ref属性,将子组件定义在$ref属性中,然后在父组件中可以通过this.$ref.给子组件定义的ref属性值 来访问子组件。

// mother

// 给daugher组件添加ref属性
<my-daughter ref="daughter"></my-daughter>

mounted() {
  // 通过refs拿到daughter的数据
 console.log(this.$refs.daughter.msg); // 我素女儿哦
 // 通过refs拿到daughter的方法
 this.$refs.daughter.sayBad(); // i think its so bad
}
// daughter

data() {
    return {
        msg: '我素女儿哦'
    }
},
methods: {
    sayBad() {
        console.log('i think its so bad');
    }
}

parent && children

子组件可以通过$parent来访问自己上一级的父组件,父组件使用$children获得的是子组件组成的数组。可以通过设置索引来访问不同的子组件。

注意:$children获得的数组是无序的。

PS: $root可以访问根组件

//mother

data() {
    return {
        name: 'cloud',
    }
},
mounted() {
    //使用$chidlren拿到女儿的信息
    console.log(this.$children[0].msg); //我素女儿哦
    //使用$chidlren拿到女儿的方法
    this.$children[0].sayGood(); // 妈妈你真棒
},
methods: {
    sayMother() {
        console.log('我素妈妈哦');
    }
}
// daughter

data() {
    return {
        msg: '我素女儿哦'
    }
},
mounted() {
    //使用$parent拿到mother组件的数据
    console.log(this.$parent.name); //cloud
    //使用$parent拿到mother组件的方法
    this.$parent.sayMother(); // 我素妈妈哦
},
methods: {
    sayGood() {
        console.log('妈妈你真棒');
    }
}

祖孙间通信

需要祖孙间通信的时候,通常会先想到 vuex,但是当项目比较小用 vuex 就没有太大的必要。

依赖provide/注入inject

依赖注入 | Vue.js (vuejs.org)

通常情况下,当我们需要从父组件向子组件传递数据时,会使用props。但当一个组件需要向一个很深层级的子组件传递数据的时候,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦,这一问题被称为“prop 逐级透传”。

provide 和 inject 可以帮助我们解决这一问题。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖

provide是一个对象,用来给子/子孙传输数据、方法或者是整个组件

inject是一个数组,用来接收父/祖父传来的数据、方法或者是整个数组

这种方式,官方不推荐,因为这个方法真的是太不好管控了,比如说我在根组件 providethis,孙孙重孙组件去使用了 this` 里面的一个变量,这时候很难去跟踪到这个变量的出处了,而且你也并不知道,项目中哪个组件有用到这个变量,有没有在其他组件中进行改变,所以这个api在项目中很少人使用,但是很多人拿来写组件用。

attrs && listeners

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

兄弟间通信

EventBus事件总线

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。 首先需要创建事件总线并将其导出,以便其它模块可以使用或者监听它。

我们可以通过两种方式来创建事件总线:

  1. event-bus.js
import Vue from 'vue'
const EventBus = new Vue();
export default EventBus
  1. main.js
//全局事件总线
new Vue({
  render: h => h(App),
  beforeCreate() {
    Vue.prototype.$bus = this // 安装全局事件总线
  }
}).$mount('#app')

使用EventBus.$emit发送消息

// friend组件

//点击触发事件
<button @click="sendMsg()">发送给daughter</button>

methods: {
    sendMsg() {
    // 发送消息
        EventBus.$emit("friendMsg", "我是你的friend");
    }
}

使用EventBus.$on监听接收消息

// daughter组件

 mounted() {
     //监听接收消息
    EventBus.$on("friendMsg", msg => {
        console.log(`daughter组件中:${msg}`); // daughter组件中:我是你的friend
    })
},

注意

如果使用不善,EventBus会是一种灾难。

  1. vue是单页应用,如果你在某一个页面刷新了之后,与之相关的EventBus会被移除,这样就导致业务走不下去。
  2. 如果业务有反复操作的页面,EventBus在监听的时候就会触发很多次,也是一个非常大的隐患。这时候我们就需要好好处理EventBus在项目中的关系。通常在vue页面销毁时,需要同时移除EventBus事件监听。
//在监听的组件中销毁,这里是daughter
beforeDesroty() {
    EventBus.$off('friendMsg');
}

PS

使用全局事件总线的话,调用this.$bus.$emitthis.$bus.$on来发送和监听消息,同时使用this.$bus.$off来移除事件监听。