组件之间的通信是面试中极为常见的问题,也是在实际工作中会经常遇到的问题,所以今天来总结一下关于组件通信方面的知识点。
父子组件通信
父 -> 子
Vue
- props: 父组件向子组件传递数据,同时可以限制传递数据的类型。
- ref: 父组件访问子组件的实例,可以调用子组件的属性和方法。
React
- props: 父组件向子组件传递数据,也可以是一个方法。
注: 虽然可以通过ref来获取子组件的实例或DOM,但是在实际项目中,并不推荐这样做。React和Vue优化的本质就是通过操作虚拟DOM,来避免操作真实DOM,提高性能。而使用ref违背了这样的初衷。
子 -> 父
Vue
- $emit('funcName', data): 子组件派发一个事件,父组件监听该事件。
子组件中:
this.$emit('hello', 'helloWorld');
父组件中:
<child @hello="sayHello" />
复制代码
React
- 调用父组件的函数: 在react中,可以通过props将父组件的函数,传递给子组件,当子组件想要通知父组件的时候,就调用父组件的函数。
// 父组件
<Child hello={this.hello} />
// 子组件
static propsTypes = {
hello: Proptypes.func
}
render() {
return {
<button onClick={this.props.hello}>hello</button>
}
}
复制代码
兄弟组件通信
Vue
- 通过共同父辈组件实现。
// 兄弟组件1
this.$parent.$on('hello',handle);
// 兄弟组件2
this.$parent.$emit('hello')
复制代码
React
- 通过共同父辈组件(状态提升) 兄弟组件A状态改变,通过调用共同父组件的函数,通知父组件。之后父组件再将兄弟组件A的信息通过props传递给兄弟组件B。
// 父组件
<A setValue={this.setValue}/>
<B value={this.state.value} />
复制代码
隔代组件通信
祖先 -> 后代
Vue
- provide/inject:能够实现祖先给后代传值。
// 祖先组件
provide() {
return {hello: 'hello'}
}
// 后代组件
inject: ['hello']
复制代码
React
- context 在react16之后的版本,重新定义了context的使用方法。所以在这里,我们就直接介绍新的版本中,如何使用context
// React.createContext 创建Context对象的API
const StatusContext = React.createContext({
disabled: false
});
// 祖先组件
<StatusContext.Provider value={{disabled: true}}>
<Children />
</StatusContext.Provider>
// 后代组件
<StatusContext.Consumer>
{context => (
<button disabled={context.disabled}>
hello
</button>
)}
</StatusContext.Consumer>
复制代码
注:
- Consumer组件的子组件必须是一个函数的形式,通过参数拿到context。
- 在react的官方文档中,提醒开发者要小心使用Context,但是在高阶组件或者React状态管理中,Context会经常被提及和使用。
后代 -> 祖先
对于后代向祖先之间的通信,其实vue和react采用的方法本质上是一样的,都是子组件一级一级向上通知。不同vue的实现相比于react的要简单的多。
// 后代组件
function dispatch(eventName, data){
let parent = this.$parent
while (parent) {
parent.$emit(eventName,data)
parent = parent.$parent
}
}
<button @click="dispatch('hello', 'hello,world')">
{{ msg }}
</button>
// 祖先组件
this.$on('hello', this.sayHello)
复制代码
任意组件中的通信
Vue
- 事件总线$Bus
// main.js
Vue.prototype.$bus = new Bus()
// 组件A
this.$bus.$on('hello', handle)
// 组件B
this.$bus.$emit('hello')
复制代码
事件总线的方式虽然可以实现任意组件中的通信,但是在实际开发中,使用的非常少。因为当项目较大时,可能会涉及到很多组件中的通信,使用$bus,会让你的代码非常杂乱。
- vuex
React
- mobx
- redux: 不同与vuex对vue的高度依赖,redux并不依赖于react,但是redux上手比较复杂,所以现在很多公司选择使用mobx。
以上就是React和Vue中常见的组件通信,如果有错误的地方,希望各位大神多多指正。