Vue(一)父子组件通信
简述在Vue中,各种组件之间他们的作用域是孤立的,因此,无法直接彼此共享数据。一个简单的实例当父组件的数据更新时,子组件能够同步数据子组件child.vue<template><div class="child"&gt
Vue 父子组件通信的三种方案
解决方法
- 使用
props
进行通信 - 使用事件分发机制(
EventBus
) $parent
属性- vuex方式 (后续补充)
结构图
一、 props p r o p s 属性
ref
被用来给子组件注册引用信息。引用信息将会注册在父组件的 $refs
对象上。
props
是在注册组件的时候进行定义,要保证props中的属性值和ref中的值是对应的。
实现原理
通过在子组件props
中定义自定义属性值,然后在父组件ref中引入该自定义属性值,并通过$refs对象传递给子组件。这样就保证了由父组件到子组件的通信。
实现源码
下面的代码演示了,父组件(parent)分别给两个子组件(child),进行传值的过程。
父组件
parent.vue
<template>
<div class="container">
<Child1 :context="obj.context"></Child1>
<Child2 :staticImgUrl="obj.url"></Child2>
</div>
</template>
import Child1 from './child1' // 引入子组件
import Child2 from './child2' // 引入子组件
export default {
name: 'parent',
components: {
Child1 // 添加子组件1
Child2 // 添加子组件2
},
data() { // 父组件的数据项
return {
obj: { //所有数据封装在obj对象中,便于管理
url: 'abc.jpg',
context:'abcdefg'
}
};
}
methods: {}
}
子组件
child1.vue
<template>
<div class="child">
<span>{{ context }}</span>
</div>
</template>
export default {
name: 'child',
components: {},
props:[ // 绑定子组件自身的属性数据
'context', // 文本
],
data() {
return {};
}
methods: {}
}
child2.vue
<template>
<div class="child">
<img src="staticImgUrl" />
</div>
</template>
export default {
name: 'child',
components: {},
props:[ // 绑定子组件自身的属性数据
'staticImgUrl', // 静态图片url
],
data() {
return {};
}
methods: {}
}
问题一 这种方式是单向通信的(局限性)
使用第一种方式的话,只能由父组件向子组件进行单向传值。子组件是无法满足向兄弟节点或者父节点进行直接通信。
一旦子组件的值发生改变,是无法修改父组件中的值的。
应用场景
父组件是一个容器,有两个子组件分别是表格(iTable)和分页器(iPage),当选中不同对页码时,要对表格内容进行更新。这种情况下使用ref/props就比较鸡肋了。
那么解决方案就是采用第二种方式(EventEmitter)
问题二 子组件修改prop值
所有的prop都是由父组件单向向下绑定的,
当父级prop得到更新的时候,子组件的所有prop都将刷新为最新的值
。因此,不应该在子组件内部修改prop的值,否则,浏览器的控制台会发出警告!!!
二、 EventBus E v e n t B u s
通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层。由于 Vue 实例实现了一个事件分发接口,你可以通过实例化一个空的 Vue 实例来实现这个目的。
这些方法的最常见用途之一是父子组件的相互通信。
这种方式也就是设计模式中的观察者模式,通过在父组件上注册监听$on
事件,当子组件要发消息给父组件的时候,直接发送$emit
事件,然后,父组件做相应的操作。
bus.js
let bus = new Vue
export default bus // 创建一个Vue实例进行事件分发
parent
<template>
<div class="parent">
</div>
</template>
export default {
name: 'parent',
components: {},
mounted: () {
// 默认监听函数放在mounted中
// 监听子节点的notify
let self = this
this.$on('display', (evt) => {
// 通知给子节点2
self.$emit('displaySuccess')
})
},
data() {
return {};
}
methods: {
}
}
child1
<template>
<div class="child" @click="dispatch">
</div>
</template>
export default {
name: 'child1',
components: {},
data() {
return {};
}
methods: {
dispatch () {
this.$emit('display')
}
}
}
child2
<template>
<div class="child2">
</div>
</template>
export default {
name: 'child2',
components: {},
mounted(){
//监听父节点的notify
this.$on('displaySuccess', (res) => {
// opts
...
})
},
data() {
return {};
}
methods: {
}
}
三、 $parent/ $ p a r e n t / $refs $ r e f s 属性
Vue 提供了一种可以从子组件访问父组件的实例$parent
,
相反,父组件可以访问子组件的实例$refs
。
$parent 和 $refs 本质上都是组件实例,因此我们可以通过实例对象访问组件内部的方法。
//parent
<template>
<Comp ref="child"></Comp>
</template>
name: 'parent',
components:{
Comp // 引入子组件
},
methods: {
notifyChild: function () {
this.$refs.child.focus() // this.$refs就是Comp组件实例
}
}
...
// child
name: 'Comp',
methods: {
focus: function () {
console.log('调用子组件',this.$parent) // this.$parent就是parent组件实例
}
}
四、 vuex v u e x 方式
上述两种方式基本满足日常开发需求,这种方式之后稍后会更新。
待续…
更多推荐
所有评论(0)