父子组件通信
props/$emit
父组件A通过props的方式向子组件B传递,
//父引用子 并发送
<childen :ParentName="name"></childen >
//ParentName为自定义名称便于子组件调用,name为要传递数据名
//子接收(数组接收直接写,对象接收可定义类型、初始值和必要性)
props:['ParentName'],
props:{
ParentName:{
type:Array,
required:true, // 如果为true则代表必须传值
default: [], // 没有传值则使用默认值,和required二选一
}
}
子组件通过$emit(事件名,参数)向外弹出一个自定义事件,在父组件中的属性监听事件,可以获得子组件中传出来的值。
// 子
<h1 @click="changeName">{{name}}</h1>//绑定一个点击事件
changeName() {
this.$emit("nameChanged","子向父组件传的值");//自定义事件 传递值
}
// 父
<children @nameChanged="updateName"><children >
updateTitle(e){ //声明这个函数
this.name= e;
}
p a r e n t / parent / parent/children(不建议使用)
$parent为当前组件树的根实例,如果当前实例没有父实例,实例将会是其自己。
$children为当前组件的直接子组件,是一个无序的数组。
// 获取到第一个子组件
this.$children[0].messageA
//获取到父组件
this.$parent.msg;
ref
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
//子
export default {
data () {
return {
title: 'Vue.js'
}
},
methods: {
sayHello () {
window.alert('Hello');
}
}
}
//父
<children ref="child"><children >
const comA = this.$refs.child;
console.log(child.title); // Vue.js
comA.sayHello(); // 弹窗
slot
子组件的数据通过插槽的方式传给父组件使用,然后再插回来
// Child.vue
<template>
<div>
<slot :user="user"></slot>
</div>
</template>
export default{
data(){
return {
user:{ name:"xxx" }
}
}
}
// Parent.vue
<template>
<div>
<child v-slot="slotProps">
{{ slotProps.user.name }}
</child>
</div>
</template>
孙子组件通信
provide / inject
祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。
// 爷爷
provide: {
name: 'tt'
}
provide: {
app: this //传所有过去
}
//孙子
inject: ['name'],
inject:{
msg:name //可赋值
}
注意! 非响应式! 然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
父组件
data(){
return{
num:1,
flag:1,
obj: {
name: 'eavan'
},
obj1: {
name: {
aa:'test1'
},
}
}
},
provide() {
return{
flag:this.flag,//不可以做到响应式
num:() => this.num,//配合计算属性实现响应式,或者直接调用num()
obj: this.obj, //是对象,能实现响应式
obj1: this.obj1 //是对象,能实现响应式(深层也可以)
}
},
子组件
inject: ['num','obj','flag','obj1'],
computed: {
numChild() {
return this.num()
},
},
a t t r s / attrs/ attrs/listeners
- a t t r s :包含了父作用域中不被认为 ( 且不预期为 ) p r o p s 的特性绑定 ( c l a s s 和 s t y l e 除外 ) ,并且可以通过 v − b i n d = " attrs:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外),并且可以通过 v-bind=" attrs:包含了父作用域中不被认为(且不预期为)props的特性绑定(class和style除外),并且可以通过v−bind="attrs" 传入内部组件。当一个组件没有声明任何 props 时,它包含所有父作用域的绑定 (class 和 style 除外)。
- l i s t e n e r s :组件的内置属性,它的值是父组件 ( 不含 . n a t i v e ) v − o n 事件监听器。组件可以通过在自己的子组件上使用 v − o n = ” listeners:组件的内置属性,它的值是父组件(不含.native) v-on事件监听器。 组件可以通 过在自己的子组件上使用v-on=” listeners:组件的内置属性,它的值是父组件(不含.native)v−on事件监听器。组件可以通过在自己的子组件上使用v−on=”listeners”,进一步把值传给自己的子组件。如果子组件已经绑定$listener中同名的监听器,则两个监听器函数会以冒泡的方式先后执行。
A组件与C组件通信时一般用B来做中转站,当A组件需要把信息传给C组件时,B接受A组件的信息,然后利用属性传给C组件,这是一种解决方案,但是如果嵌套的组件过多,会导致代码繁琐,代码维护比较困难;如果C中状态的改变需要传递给A, 使用事件系统一级级往上传递 。
//爷爷
<child @test1='testOne' @test2='testTwo' :name="name" :age="age">
//父
props: ['name'],
<son v-bind="$attrs" v-on="$listeners" :weight="weight" >
//子
props: ['weight'], //继承所有父组件属性,除了props传递的
this.$emit('test1','eee') //可触发爷爷组件的test1函数
任意组件通信
eventBus事件总线
//发送
EventBus.$emit('post',{
name:'tt'
})
//接收
EventBus.$on("post", msg => {
console.log(msg)
});