父子组件通信
1.父组件向子组件传值
父组件通过使用子组件标签,在内部配置v:bind指令传属性,也就是:title=“title” :obj="obj"等等,而子组件通过配置props:{}来接收父组件传递过来的属性
**父组件**
<template>
<div class="father">
<son :title="title" :obj="obj"></son>
</div>
</template>
<script>
import son from './component/son';
export default {
name: 'index',
components: {
son,
},
data () {
return {
title: '父组件的title',
obj: {
value: 'value',
},
};
},
};
</script>
**子组件**
<template>
<div class="son">
<div>title:{{title}}</div>
<div>obj的value:{{obj.value}}</div>
</div>
</template>
<script>
export default {
name: 'son',
props: {
title: {
type: String,
default: '',
},
obj: {
type: Object,
default: () => ( {} ),
},
},
};
</script>
2.子组件修改父组件属性,调用父组件方法
- 方法一:子组件配置 $emit传值, 父组件配置 v-on 接收
**父组件**
<template>
<div class="father">
<son
:title="title"
@changeTitle="changeTitle"
@logFun="logFun"></son>
</div>
</template>
<script>
import son from './component/son';
export default {
name: 'index',
components: {
son,
},
data () {
return {
title: '',
};
},
methods: {
logFun () {
console.log( '父组件的输出' );
},
changeTitle ( title ) {
this.title = title;
},
},
};
</script>
**子组件**
<template>
<div class="son">
<el-button type="primary" @click="changetitle">
改变父组件title值
</el-button><br>
<el-button type="primary" @click="useFatherFun">
调用父组件方法
</el-button><br>
</div>
</template>
<script>
export default {
name: 'son',
props: {
title: {
type: String,
default: '',
},
},
methods: {
// 改变父组件title值
changetitle () {
this.title = this.title + '!';
this.$emit( 'changeTitle', this.title );
},
// 调用父组件logFun方法
useFatherFun () {
this.$emit( 'logFun' );
},
},
};
</script>
- 方法二:
-
- 使用.sycn修饰符 通过“双向数据绑定”的形式更改props值,这种方式可以省去父组件用v-on接收
- 使用.sycn修饰符 通过“双向数据绑定”的形式更改props值,这种方式可以省去父组件用v-on接收
-
- 通过包装对象的形式更改props传递的值(不推荐,避免这个参数多个子组件引用,无法找到造成数据不正常的原因;违反vue的prop单向下行绑定规范)
- 通过包装对象的形式更改props传递的值(不推荐,避免这个参数多个子组件引用,无法找到造成数据不正常的原因;违反vue的prop单向下行绑定规范)
-
- 在子组件中改变数组(使用改变原数组的数组方法对数组进行操作)(不推荐)
- 在子组件中改变数组(使用改变原数组的数组方法对数组进行操作)(不推荐)
-
- 使用this.parent可以获取父组件的属性、方法,如果多个父组件都拥有这个属性/方法,则都调用)
**父组件**
<template>
<div class="father">
<div>title:{{title}}</div>
<div>obj:{{obj.value}}</div>
<div>arr:{{arr}}</div>
<div>text.value:{{text.value}}</div>
<son
:title.sync="title"
:obj="obj"
:arr="arr"
:text.sync="text"></son>
</div>
</template>
<script>
import son from './component/son';
export default {
name: 'index',
components: {
son,
},
data () {
return {
title: '',
obj: {
value: 'value',
},
arr: [1, 2],
text: {
value: '请输入姓名',
},
};
},
methods: {
logFun () {
console.log( '父组件的输出' );
},
},
};
</script>
**子组件**
<template>
<div class="son">
<!--与父组件的通信-->
<el-button type="primary" @click="changetitle">
通过“双向数据绑定”的形式更改props值
</el-button><br>
<el-button type="primary" @click="changeValue">
通过包装对象的形式更改props传递的值
</el-button><br>
<el-button type="primary" @click="changeArr">
在子组件中改变数组
</el-button><br>
<el-input type="primary" v-model="text.value"></el-input>
<el-button type="primary" @click="useFatherFun">
调用父组件方法
</el-button>
</div>
</template>
<script>
export default {
name: 'son',
components: {
grandSon,
},
data () {
return {
age: 12,
name: '李四',
};
},
props: {
title: {
type: String,
default: '',
},
obj: {
type: Object,
default: () => ( {} ),
},
arr: {
type: Array,
default: () => ( [] ),
},
text: {
type: Object,
default: () => ( {} ),
},
},
methods: {
// 改变父组件title值
changetitle () {
this.title = this.title + '!';
this.$emit( 'update:title', this.title );
},
// 改变父组件obj.value值
changeValue () {
this.obj.value = 'value1';
},
// 改变父组件arr值(改变原数组的方法都可以)
changeArr () {
this.arr.push( 3 );
// pop、shift、unshift、splice、sort都可
},
// 调用父组件的方法
useFatherFun () {
this.$parent.logFun();
}
},
};
</script>
3. 父组件调用子组件方法
- 方法一:$refs
<son ref="sonCom"></son>
this.$refs.sonCom.sonFun(); // 给子组件绑定ref 通过this.$ref调用子组件的方法
- 方法二:$children
-
- 利用$children获取到的是一个数组,访问其中的组件必须通过索引值。
-
- 由于可能会使用外部组件库如elementUI中的组件,也会被识别为子组件,有可能会造成混淆
-
- 当子组件过多时,往往不能确定他的索引值
-
- $children可以获取子组件的属性、方法
this.$children[0].sonFun(); // sonFun是子组件一的方法
this.$children[1].sonFun2(); // sonFun2是子组件二的方法
兄弟组件通信
- 两个子组件通过父组件通信
- vuex
- 全局事件总线
在main.js中定义全局事件总线
new Vue( {
el: '#app',
render: h => h( App ),
beforeCreate () {
Vue.prototype.$eventBus = this; // beforeCreate钩子函数里this指代new出来的vm
},
} );
或Vue.prototype.$eventBus = new Vue()
**组件一**
<template>
<div class="son">
<el-button type="primary" @click="changeName">
给兄弟组件son1传name
</el-button><br>
<el-button type="primary" @click="transmitAge">
给兄弟组件son1传age
</el-button><br>
</div>
</template>
<script>
export default {
name: 'son',
components: {
grandSon,
},
data () {
return {
age: 12,
name: '李四',
};
},
methods: {
// 给兄弟组件son1传name
changeName () {
this.$eventBus.$emit( 'getName', this.name );
},
// 给兄弟组件son1传age
transmitAge () {
this.$eventBus.$emit( 'getAge', this.age );
},
},
};
</script>
**组件二**
<template>
<div class="son1">
姓名:{{name}}
年龄:{{age}}
</div>
</template>
<script>
export default {
name: 'son1',
data () {
return {
name: '张三',
age: 0,
};
},
mounted () {
// 获取兄弟组件son传来的name
this.$eventBus.$on( 'getName', ( name ) => {
this.name = name;
} );
// 获取兄弟组件son传来的age
this.$eventBus.$on( 'getAge', ( age ) => {
this.age = age;
} );
},
// 销毁“全局事件总线”中定义的自定义事件
// “全局事件总线”中定义的自定义函数是一直存在的,哪怕使用组件销毁了,但是Vue实力定义的“全局事件总线”中还是会存在自定义事件,所以需要在组件销毁之前进行解绑
beforeDestroy () {
this.$eventBus.$off( 'getName' );
this.$eventBus.$off( 'getAge' );
},
};
</script>
祖孙组件通信
- 全局事件总线$eventBus
- vuex
- 使用listener
祖A 父B 孙C, B调用C时使用v-on绑定listeners ,通过v−bind绑定attrs,C组件可以直接获取到A组件传递下来的props,除了B中props接收过的 (attrs将B未接收的A组件的绑定传给C,listeners将B未接收的A的监听传给C)
**A**
<template>
<div>
<div>这是孙组件的grandSonInfo:{{grandSonInfo}}</div>
<son
:title="title"
:grandSonText="grandSonText"
:grandSonInfo.sync="grandSonInfo"
@logFun="logFun"></son>
<son1></son1>
</div>
</template>
<script>
import son from './component/son';
import son1 from './component/son1';
export default {
name: 'index',
components: {
son,
son1,
},
data () {
return {
title:'父组件的title',
grandSonText: 'grandSon信息',
grandSonInfo: 'grandSonInfo',
};
},
methods: {
logFun () {
console.log( '父组件的输出' );
},
},
};
</script>
**B**
<template>
<div class="son">
父组件的title:{{title}}
<grand-son v-bind="$attrs" v-on="$listeners"></grand-son>
</div>
</template>
<script>
import grandSon from './grandSon';
export default {
name: 'son',
components: {
grandSon,
},
props: {
title: {
type: String,
defult: '',
},
},
data () {
return {
age: 12,
name: '李四',
};
},
};
</script>
**C**
<template>
<div>
<div>grandSonText:{{grandSonText}}</div>
<div>grandSonInfo:{{grandSonInfo}}</div>
<el-button type="success" @click="changeGrandSonInfo">
改变祖组件A的grandSonInfo
</el-button>
<el-button type="success" @click="useLogFun">
调用祖组件A的logFun
</el-button>
</div>
</template>
<script>
export default {
name: 'grandSon',
props: {
grandSonText: {
type: String,
default: '',
},
grandSonInfo: {
type: String,
default: '',
},
logFun: {
type: Function,
default: () => () => ( {} ),
},
},
methods: {
// 改变祖组件A的grandSonInfo的值
changeGrandSonInfo () {
this.$emit( 'update:grandSonInfo', this.grandSonInfo + '~' );
},
// 调用祖组件A的logFun方法
useLogFun () {
this.$emit( 'logFun' );
},
},
};
</script>