Featured image of post vue 组件通信

vue 组件通信

在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。 父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的。 图片来自vuejs.org

父组件通过 prop 给子组件下发数据:

1
2
3
4
5
Vue.component('child', {
  // 在 JavaScript 中使用 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
1
2
<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child>

子组件通过事件给父组件发送消息:

1
2
3
4
5
<div id="message-event-example" class="demo">
  <p v-for="msg in messages">{{ msg }}</p>
  <button-message v-on:message="handleMessage"></button-message>
  <!-- 使用 $on(eventName) 监听事件 -->
</div>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Vue.component('button-message', {
  template: `<div>
    <input type="text" v-model="message" />
    <button v-on:click="handleSendMessage">Send</button>
  </div>`,
  data: function () {
    return {
      message: 'test message'
    }
  },
  methods: {
    handleSendMessage: function () {
      this.$emit('message', { message: this.message })   // 使用 $emit(eventName, optionalPayload) 触发事件 
    }
  }
})

new Vue({
  el: '#message-event-example',
  data: {
    messages: []
  },
  methods: {
    handleMessage: function (payload) {
      this.messages.push(payload.message)
    }
  }
})

非父子组件通信

有时候两个组件也需要通信(非父子关系)。在简单的场景下可是使用一个空的vue实例作为中央事件总线:

1
let bus = new Vue()
1
2
3
4
5
6
7
//触发组件 A 中的事件
bus.$emit('is-selected', 1)
``````js
//在组件 B 创建的钩子中监听事件
bus.$on('is-selected', function(id){

})

这个集中式的事件中间件就是 Bus。可以将bus定义到全局: app.js

1
2
3
4
5
6
var eventBus = {
    install(Vue,options) {
        Vue.prototype.$bus = vue
    }
};
Vue.use(eventBus);

然后在组件中,可以使用$emit, $on, $off 分别来分发、监听、取消监听事件: 分发事件的组件

1
2
3
4
5
6
7
// ...
methods: {
  todo: function () {
    this.$bus.$emit('todoSth', params);  //params是传递的参数
    //...
  }
}

监听的组件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// ...
created() {
  this.$bus.$on('todoSth', (params) => {  //获取传递的参数并进行操作
      //todo something
  })
},

// 最好在组件销毁前
// 清除事件监听
beforeDestroy () {
  this.$bus.$off('todoSth');
},

如果需要监听多个组件,只需要更改 bus 的 eventName:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// ...
created() {
  this.$bus.$on('firstTodo', this.firstTodo);
  this.$bus.$on('secondTodo', this.secondTodo);
},
// 清除事件监听
beforeDestroy () {
  this.$bus.$off('firstTodo', this.firstTodo);
  this.$bus.$off('secondTodo', this.secondTodo);
},
Licensed under CC BY-NC-SA 4.0