Open ghost opened 5 years ago
适用于父子组件之间通信。
通过props向子组件传递数据:
props
<template> <bar :name="name"></bar> </template> <script> // foo.vue import Bar from './bar'; export default { name: 'foo', components: [Bar], data() { return { name: 'name' }; } }; </script>
传递数据之前,需要在子组件定义中声明props:
// bar.vue export default { name: 'bar', props: { name: String } }
通过事件从子组件向父组件抛出数据:
// bar.vue export default { name: 'bar', props: { name: String }, methods: { changeName(newName) { this.name = newName; this.$emit('change', this.name); // 抛出change事件 } } }
在父组件中监听子组件抛出的事件:
<template> <bar :name="name" @change="handleChange"></bar> </template> <script> // foo.vue import Bar from './bar'; export default { name: 'foo', components: [Bar], data() { return { name: 'name' }; }, methods: { handleChange(val) { this.name = val; } } }; </script>
对于如上示例,还可以使用v-modle和.sync进行改写,请读者自行实现。
v-modle
.sync
适用于任何组件结构之间的通信,基本原理也是事件机制。
创建一个全局Bus:
Bus
// bus.js import Vue from 'vue'; export default new Vue();
在事件发起组件中,通过bus发起事件:
bus
// bar.vue import Bus from './bus'; export default { name: 'bar', mounted() { Bus.$emit('change', newVal) // 通过Bus发起事件,并传递数据 } };
在事件目标组件中,通过bus接受事件:
// foo.vue import Bus from './bus'; export default { name: 'foo', created() { Bus.$on('change', newVal => { console.log(newVal); }) // 接受到数据 } };
Bus就是一个vue实例,vue实例实现了事件机制,因此我们可以通过它来做中间人,通过中间人传递数据。
vue实例
中间人
Vuex是一个独立的状态管理工具,它可用在任意组件结构之间通信。
Vuex
状态管理工具
将共享状态放入vuex:
vuex
const CHANGE_NAME = 'CHANGE_NAME'; { state: { name: 'name' }, getters: { name: state => state.name }, mutations: { [CHANGE_NAME](state, payload) { state.name = payload.name; } }, actions: { changeName({ commit }, payload) { commit(CHANGE_NAME, payload) } } }
从vuex获取数据:
<template> <span> {{ name }}</span> </template> <script> // foo.vue import { mapGetters } from 'vuex'; export default { name: 'foo', computed: { ...mapGetters(['name']) } }; </script>
通过vuex action改变数据:
vuex action
// bar.vue import { mapActions } from 'vuex'; export default { name: 'bar', mounted() { this.changeName({ name: newVal }); }, methods: { ...mapActions(['changeName']) } };
适用于深层次嵌套组件中,祖先组件向子孙组件传递数据。
深层次嵌套组件
祖先组件向子孙组件
在祖先组件使用provide提供数据:
祖先组件
provide
// foo.vue export default { name: 'foo', data() { return { name: 'name' }; }, provide() { return { name: this.name }; } };
在子孙组件使用inject注入数据:
子孙组件
inject
// bar.vue <template> <span>{{ name }}</span> </template> <script> export default { name: 'bar', inject: ['name'] }; </script>
祖先组件与子孙组件的嵌套关系:
祖先组件与子孙组件
<foo> ... <other-component> <bar></bar> </other-component> ... </foo>
适用于祖先组件向子孙组件传递数据,且所有后代组件均会收到广播。
后代组件
首先实现一个事件发射与广播的mixin:
事件发射与广播
mixin
// emitter.js function broadcast(componentName, eventName, params) { this.$children.forEach(child => { var name = child.$options.componentName; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { broadcast.apply(child, [componentName, eventName].concat([params])); } }); } export default { methods: { // 向指定的祖先组件发射事件 dispatch(componentName, eventName, params) { var parent = this.$parent || this.$root; var name = parent.$options.componentName; while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.componentName; } } // 找到指定的祖先组件,触发其$emit方法,传递事件名和参数 if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, // 向所有指定的子孙组件广播事件 broadcast(componentName, eventName, params) { broadcast.call(this, componentName, eventName, params); } } };
在祖先组件中引入mixin,通过广播传递数据:
广播
// foo.vue import emitter from './emitter'; export default { name: 'foo', mixins: [emitter], data() { return { name: 'name' }; }, mounted() { this.broadcast('bar', 'changeName', newVal); } };
在子孙组件中接受广播的事件:
// bar.vue export default { name: 'bar', created() { this.$on('changeName', newVal => console.log(newVal)) } };
适用于后代组件向祖先组件派遣数据。
在子孙组件引入mixin,向祖先组件派遣事件:
// bar.vue import emitter from './emitter'; export default { name: 'bar', mixins: [emitter], mounted() { this.dispatch('foo', 'changeName', newVal); } };
在祖先组件中接受来自子孙组件的数据:
// foo.vue export default { name: 'foo', created() { this.$on('changeName',newVal => console.log(newVal)); } };
Vue组件间的通信方案
Props与事件机制
适用于父子组件之间通信。
通过
props
向子组件传递数据:传递数据之前,需要在子组件定义中声明
props
:通过事件从子组件向父组件抛出数据:
在父组件中监听子组件抛出的事件:
对于如上示例,还可以使用
v-modle
和.sync
进行改写,请读者自行实现。Bus机制
适用于任何组件结构之间的通信,基本原理也是事件机制。
创建一个全局
Bus
:在事件发起组件中,通过
bus
发起事件:在事件目标组件中,通过
bus
接受事件:使用Vuex
Vuex
是一个独立的状态管理工具
,它可用在任意组件结构之间通信。将共享状态放入
vuex
:从
vuex
获取数据:通过
vuex action
改变数据:provide与inject
适用于
深层次嵌套组件
中,祖先组件向子孙组件
传递数据。在
祖先组件
使用provide
提供数据:在
子孙组件
使用inject
注入数据:祖先组件与子孙组件
的嵌套关系:事件广播机制
适用于
祖先组件向子孙组件
传递数据,且所有后代组件
均会收到广播。首先实现一个
事件发射与广播
的mixin
:在
祖先组件
中引入mixin
,通过广播
传递数据:在
子孙组件
中接受广播的事件:事件调度(dispatch)机制
适用于
后代组件
向祖先组件
派遣数据。在
子孙组件
引入mixin
,向祖先组件
派遣事件:在
祖先组件
中接受来自子孙组件
的数据: