vue组件间通信的四种方法
0 四种方式
- 父子传参
- 事件总线 bus
- provided/injected
- Vuex
1 父子组件通信
父传子props
, 子传父$emit
2 兄弟
通过父组件转发
老大->父组件->老二 (单向)
- One.vue 老大提交自定义事件
<template>
<div>
老大子组件:
<input type="text" v-model="msg" />
<button @click="$emit('send',msg)">发送</button>
</div>
</template>
<script>
export default {
name: 'One',
data() {
return { msg: '' }
},
}
</script>
- Two.vue 老二接收参数
<template>
<div>老二子组件: {{ msg }}</div>
</template>
<script>
export default {
name: 'Two',
props: {
msg: { type: String },
},
}
</script>
- App.vue 父组件监听自定义事件
<template>
<div id="app">
<one @send="handleSend"></one>
<two :msg="msg"></two>
</div>
</template>
<script>
import One from './components/One.vue'
import Two from './components/Two.vue'
export default {
name: 'App',
components: {
One,
Two,
},
data() {
return {
msg: '',
}
},
methods: {
handleSend(msg) {
this.msg = msg
},
},
}
</script>
3 表兄弟
3.1 介绍
全局事件总线bus
(适合两个组件间通信, 没有明显关系的两个组件)
所有的组件都通过一个统一的全局对象通信
多个组件, 用vuex
3.2 事件总线用法
- bus/index.js
import Vue from 'vue'
// 这是一个Vue实例对象
const bus = new Vue()
export default bus
- Counter.vue 发
<template>
<div>
<button @click="handleClick">向Test发送消息</button>
</div>
</template>
<script>
import bus from '@/bus'
export default {
name: 'Counter',
data() {
return {
msg: '',
}
},
methods: {
handleClick() {
// 在一个组件中触发事件
bus.$emit('send', this.msg)
},
},
}
</script>
- Test.vue 收
<template>
<div>
从counter中收到的消息 {{ msg }}
</div>
</template>
<script>
import bus from '@/bus'
export default {
name: 'Test',
data() { return { msg: '' } },
mounted() {
// 监听自定义事件
bus.$on('send', (value) => {
this.msg = value
})
},
beforeDestroy() {
// 移除自定义事件
bus.$off('send')
},
}
</script>
4 祖孙组件通信
依赖注入 provided/injected (vue3直接是响应式)
1) 传静态数据
1) 在祖先组件中通过 provid
选项提供数据
2) 在后代组件中通过injection
选项注入数据
- App.vue
// 父级组件提供 'foo'
export default {
name: 'App',
provide: {
foo: 'hello'
},
// ...
}
- son.vue
// 孙子组件注入 'foo'
export default {
name: 'Son',
inject: ['foo'],
created () {
console.log(this.foo)
}
}
2) 传响应式数据
传入对象
- App.vue
<template>
<div id="app">
<input type="text" v-model="obj.msg" />
</div>
</template>
<script>
export default {
name: 'App',
provide() {
return { foo: this.obj }
},
data() { return { obj: { msg: '' } } },
}
</script>
- son.vue
<template>
<div>{{ foo.msg }}</div>
</template>
<script>
export default {
name: 'Son',
inject: ['foo'],
}
</script>
传入函数
- App.vue
<template>
<div id="app">
<input type="text" v-model="msg" />
<counter></counter>
<test></test>
</div>
</template>
<script>
export default {
name: 'App',
provide() {
// provide设置为一个函数, 该函数中this指向vm实例
return { foo: () => this.msg }
},
data() { return { msg: '' } },
}
</script>
- son.vue
<template>
<div>{{ foo() }}</div>
</template>
<script>
export default {
name: 'Son',
inject: ['foo'],
}
</script>