Vue 组件之间的通信
- 父子组件通信
父组件 -> 子组件:props
// section父组件
<template>
<div class="section">
<com-article :articles="articleList"></com-article>
</div>
</template>
<script>
import comArticle from './test/article.vue'
export default {
name: 'HelloWorld',
components: { comArticle },
data() {
return {
articleList: ['红楼梦', '西游记', '三国演义']
}
}
}
</script>
// 子组件 article.vue
<template>
<div>
<span v-for="(item, index) in articles" :key="index">{{item}}</span>
</div>
</template>
<script>
export default {
props: ['articles']
}
</script>
// 子组件通过 props 来接收 父组件传来的值。
Vue.component('Child', {
template: '<h2>{{ content }}</h2>',
props: {
content: {
type: String,
default: () => { return 'from child' }
}
}
})
new Vue({
el: '#app',
data: {
message: 'from parent'
},
components: {
Child
}
})
// 浏览器输出 from parent
子组件 -> 父组件:$on/$emit
<div id="app">
<my-button @greet="sayHi"></my-button>
</div>
// 我在页面上点击按钮时,触发了组件 MyButton 上的监听事件 greet,并且把参数传给了回调函数 sayHi 。
// 当我们从子组件 Emit(派发) 一个事件之前,其内部都提前在事件队列中 On(监听)了这个事件及其监听回调。
Vue.component('my-buttton', {
template: '<button @click="triggerClick">click</button>',
data () {
return {
greeting: 'vue.js!'
}
},
methods: {
triggerClick () {
this.$emit('greet', this.greeting)
}
}
})
new Vue({
el: '#app',
components: {
MyButton
},
methods: {
sayHi (val) {
alert('Hi, ' + val) // 'Hi, vue.js!'
}
}
})
// 其实相当于:
vm.$on('greet', function sayHi (val) {
console.log('Hi, ' + val)
})
vm.$emit('greet', 'vue.js')
// => "Hi, vue.js"
获取组件实例:使用$parent/$children
,$refs.xxx
,获取到实例后直接获取属性数据或调用组件方法
// 父组件中
<template>
<div class="hello_world">
<div>{{msg}}</div>
<com-a ref="comA"></com-a>
<button @click="changeA">点击改变子组件值</button>
</div>
</template>
<script>
import ComA from './test/comA.vue'
export default {
name: 'HelloWorld',
components: { ComA },
data() {
return {
msg: 'Welcome'
}
},
mounted () {
const comA = this.$refs.comA;
console.log(comA.name); // Vue.js
},
methods: {
changeA() {
// 获取到子组件A
this.$children[0].messageA = 'this is new value'
}
}
}
</script>
// 子组件中
<template>
<div class="com_a">
<span>{{messageA}}</span>
<p>获取父组件的值为: {{parentVal}}</p>
</div>
</template>
<script>
export default {
data() {
return {
messageA: 'this is old'
name: 'Vue.js'
}
},
computed:{
parentVal(){
return this.$parent.msg;
}
}
}
</script>
- 兄弟组件通信
Event Bus:每一个Vue实例都是一个Event Bus,都支持$on/$emit
,可以为兄弟组件的实例之间new一个Vue实例,作为Event Bus进行通信。
- 初始化
首先需要创建一个事件总线并将其导出, 以便其他模块可以使用或者监听它.
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
- 发送事件
创建2个组件:additionNum
和showNum
, 该组件为兄弟组件。
<template>
<div>
<show-num-com></show-num-com>
<addition-num-com></addition-num-com>
</div>
</template>
<script>
import showNumCom from './showNum.vue'
import additionNumCom from './additionNum.vue'
export default {
components: { showNumCom, additionNumCom }
}
</script>
// addtionNum.vue 中发送事件
<template>
<div>
<button @click="additionHandle">+加法器</button>
</div>
</template>
<script>
import {EventBus} from './event-bus.js'
console.log(EventBus)
export default {
data(){
return{
num:1
}
},
methods:{
additionHandle(){
EventBus.$emit('addition', {
num:this.num++
})
}
}
}
</script>
- 接收事件
// showNum.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>
- 移除事件监听者
import { eventBus } from 'event-bus.js'
EventBus.$off('addition', {})
Vuex:将状态和方法提取到Vuex,完成共享, 使用方法vuex 介绍
- 跨级组件通信
使用provide/inject
provide/ inject 是vue2.2.0新增的api, 简单来说就是父组件中通过provide来提供变量, 然后再子组件中通过inject来注入变量。
Event Bus:同兄弟组件Event Bus通信
// A.vue
<template>
<div>
<comB></comB>
</div>
</template>
<script>
import comB from '../components/test/comB.vue'
export default {
name: "A",
provide: {
for: "demo"
},
components:{
comB
}
}
</script>
// B.vue
<template>
<div>
{{demo}}
<comC></comC>
</div>
</template>
<script>
import comC from '../components/test/comC.vue'
export default {
name: "B",
inject: ['for'],
data() {
return {
demo: this.for
}
},
components: {
comC
}
}
</script>
// C.vue
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "C",
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>
Vuex:将状态和方法提取到Vuex,完成共享。使用见vuex 介绍