常见的通信方式都有哪些?
1. props $emit
子组件中通过props 接受父组件传递的参数,同时通过事件触发emit, 发送数据给父组件。父组件中通过事件绑定获取子组件传递的参数。
优先推荐这个种方法。原因有这些:1. 子组件中可以规范接受的参数,它是什么数据类型,以及默认值。2. 在通过emit传递给父级数据,保证数据的实时性。
基本代码展示:
// child
//子组件
<template>
<div>
<div @click="sendMsg('i am your child')">父组件传递过来的:{{getdatafromfather}}</div>
</div>
</template>
<script>
export default {
props: ['getdatafromfather'],
methods: {
sendMsg(data) {
this.$emit('getdatafromchild', data) // 触发父组件的方法,并传递参数data
}
}
}
</script>
// 父组件
<template>
<div class="section">
<child :getdatafromfather="fatherMsg" @getdatafromchild="getData"></child>
<p>我自己的:{{fatherMsg}}</p>
<p>子组件给我的:{{getMsg}}</p>
</div>
</template>
<script>
import child from './child.vue'
export default {
name: 'father',
components: { child },
data() {
return {
fatherMsg: 'vue man', // 父级本地的数据
getMsg: '' // 由于子组件传递的数据
}
},
methods: {
// 事件绑定,由子组件触发
getData(id) {
this.getMsg = idx
}
}
}
</script>
2. $refs
ref 关键字 类似一个dom的id, 你可以通过给一个组件设置ref=“idRef”,并且通过$refs.idRef获取到这个组件的数据和方法且获取的数据不是响应式。特点是子组件中不需要做任何信息的配置。
// father
<template>
<child ref="child"></component-a>
</template>
<script>
import child from './child.vue'
export default {
components: { child },
data() {
return {
fatherData: 'father'
}
}
mounted () {
console.log(this.$refs.child.name); // child
this.$refs.child.sayHello(); // hello
}
}
</script>
// child
<template>
<div></div>
</template>
<script>
import child from './child.vue'
export default {
data() {
return {
name: 'child'
}
}
components: { child },
methods: {
sayHello() {
console.log('hello');
}
}
}
</script>
3. children parent
1.使用$ parent 可以让组件访问父组件的实例(访问的是上一级父组件的属性和方法)
2.使用$ children 可以让组件访问子组件的实例,但是,$children并不能保证顺序,并且访问的数据也不是响应式的。
特点是:父子组件中代码,都不需要有改动, 方便直接访问。
// 使用 2 中的代码例子
// child.vue
mounted: {
console.log($parent.fatherData); // father
}
// 使用 2 中的代码例子
// father.vue
mounted: {
console.log($children[0].name); // child
}
4. eventbus 事件总线
eventBus事件总线适用于父子组件、非父子组件等之间的通信。特点是要在全局注册总线,适用于兄弟组件 和 父子组件通信。优先推荐兄弟组件的通信。因为项目大的时候,维护起来麻烦。下面是关键代码样例:
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
<template>
<div>
<a-dom></a-dom>
<b-dom></b-dom>
</div>
</template>
<script>
import aDom from './aDom.vue'
import bDom from './bDom.vue'
export default {
components: { aDom, bDom }
}
</script>
// a-dom.vue
<template>
<div>
<button @click="add">加法</button>
</div>
</template>
<script>
import {EventBus} from './event-bus.js' // 引入事件中心
export default {
data(){
return{
num:0
}
},
methods:{
add(){
// 事件分发
EventBus.$emit('addition', {
num:this.num++
})
}
}
}
</script>
// b-dom.vue
<template>
<div>求和: {{count}}</div>
</template>
<script>
import { EventBus } from './event-bus.js'
export default {
data() {
return {
count: 0
}
},
mounted() {
EventBus.$on('addition', param => {
this.count = this.count + param.num;
})
}
}
</script>
5. 依赖注入(provide/ inject)
该方式适合直系亲属通信。类似父与子,父与孙子等。推荐是在组件嵌套层级很深的情况,并且信息传递方向只能是高层级传递给低层级。注意: 依赖注入所提供的属性是非响应式的。
provide / inject是Vue提供的两个钩子,和data、methods是同级的。并且provide的书写形式和data一样。
provide 发送数据或方法
inject 接收数据或方法
下面是关键代码样例:
// father.vue
<template>
<div>
<ChildComponent />
</div>
</template>
<script>
import Vue from 'vue'
import ChildComponent from './ChildComponent'
export default {
components: {
ChildComponent
},
provide() {
return {
foo: 'bar'
}
}
}
</script>
// child.vue/childschild.vue
<template>
<div>
{{ foo }}
</div>
</template>
<script>
export default {
inject: ['foo'],
mounted() {
console.log(this.foo) // 'bar'
}
}
</script>