
前言
上一章节我们一起学习了通过SDK的设计,了解了 SDK 设计中的事件监听模型,同样 EventEmitter 也可以作为中介者模型来实现组件之间的跨级通信。
本章节我们就一起来学习几种通用的组件通信模型, 同时通过中介者模型实现组件元素之间跨级通信。
开箱即用的源码
源码地址:https://github.com/dkypooh/front-end-develop-demo/tree/master/base/babel7-react
组件通信模式
本小节以 React 组件框架为例,和大家一起探讨学习几种通用的组件通信模型。
- 父组件到子组件:
props属性 ,instance methods实例方法 - 子组件到父组件:
callback回调方法,event bubbles事件冒泡 - 临近兄弟节点:
Parent Component父组件 - 任何节点:
Observer Pattern观察者模式,Global Variables全局变量,ContextReact执行上下文
父组件到子组件
Props
Props 是一个父节点到一个子节点通信最常见的方式。
class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}</h1>;}}
ReactDOM.render(<Welcome name="Sara" />,document.getElementById('root'));
Instance Methods
父组件可以使用refs调用子组件上的实例方法
class TheChild extends React.Component {myFunc() {return "hello";}}
class TheParent extends React.Component {render() {return (<TheChildref={foo => {this.foo = foo;}}/>);}componentDidMount() {var x = this.foo.myFunc();// x is now 'hello'}}
子组件到父组件
Callback Functions
最简单的方法是父组件将函数传递给子组件,子组件调用父组件的方法
以属性的方式传递函数
<MyChild myFunc={this.handleChildFunc} />
子组件调用方式
this.props.myFunc();
添加属性函数声明
MyChild.propTypes = {myFunc: React.PropTypes.func};
Event Bubbling
事件冒泡不是 React 的概念,它是DOM元素的概念,它可以像回调函数一样通过冒泡方式把数据通子组件发送到父组件。
class ParentComponent extends React.Component {render() {return (<div onKeyUp={this.handleKeyUp}>// Any number of child components can be added here.</div>);}handleKeyUp = (event) => {// This function will be called for the 'onkeyup'// event in any <input/> fields rendered by any of// my child components.}}
临近兄弟节点
父组件通信
如果两个相邻组件需要通信, 我们可以找到他们相邻的父节点进行中转通信
class ParentComponent extends React.Component {render() {return (<div><SiblingAmyProp={this.state.propA}myFunc={this.siblingAFunc}/><SiblingBmyProp={this.state.propB}myFunc={this.siblingBFunc}/></div>);}// Define 'siblingAFunc' and 'siblingBFunc' here}
任何节点
全局变量
组件中都可以引用到全局变量,一般可以挂载到 window 对象上面,切记不要滥用他们
window.x = 'global variable'
Context
Context 使用类似于 Props, 和 Props 区别在于它可以提供整个树形组件的数据(多级子组件), Context 只能向下数据传递(父组件到子组件),可以配合 callback functions 一起使用(子组件到父组件)。
使用 Props 实例
class App extends React.Component {render() {return <Toolbar theme="dark" />;}}function Toolbar(props) {return (<div><ThemedButton theme={props.theme} /></div>);}class ThemedButton extends React.Component {render() {return <Button theme={this.props.theme} />;}}
使用 Context 实例
// 创建 Context 实例const ThemeContext = React.createContext('light');class App extends React.Component {render() {return (// 提供 `Provider` 上下文容器<ThemeContext.Provider value="dark"><Toolbar /></ThemeContext.Provider>);}}function Toolbar(props) {return (<div><ThemedButton /></div>);}class ThemedButton extends React.Component {dstatic contextType = ThemeContext;render() {return <Button theme={this.context} />;}}
中介者模式通信
本小节和大家一起探讨学习,通过中介者模式实现组件元素之间跨级通信。同理 Redux 状态管理也是采用中介者模式实现 数据状态扁平化管理
不需要考虑A,B,C组件的树形关系,这样就可以实现扁平化通信,如图:A组件的行为就可以被B和C组件响应。
EventBus实现
EventBus 模块实现引用的是通用SDK的 event 模块。实现事件发布和监听管理。 代码可以参考上一章节(设计模式 - EventEmitter实现)
EventBus源码地址
源码地址:https://github.com/dkypooh/front-end-develop-demo/tree/master/base/babel7-react/src/common/eventBus
组件通信实例
不通过父子组件属性和回调函数通信, 通过 EventBus 中介者模式实现一个加减计数器组件。
目录结构
├── src│ ├── common│ │ ├── event.js│ │ └── eventBus│ │ ├── event.d.ts│ │ ├── event.js│ │ └── event.ts│ ├── components│ │ ├── add│ │ │ └── index.jsx│ │ └── show│ │ └── index.jsx│ └── index.jsx
Add 组件
import React from "react";import event from '../../common/event';export default class extends React.PureComponent {handleAdd() {// 触发加号事件event.emit('add');}handleReduce() {// 触发减号事件event.emit('reduce');}render() {return (<div className="m-opt"><div onClick={() => {this.handleAdd()}}>+</div><div onClick={() => {this.handleReduce()}}>-</div></div>);}}
Show 组件
import React from "react";import event from '../../common/event';export default class extends React.PureComponent {constructor(props) {super(props);this.state = {number: 0};// 监听减号事件,并把 `number` 字段减一event.on('reduce', () => {this.setState({number: this.state.number - 1});});// 监听加号事件,并把 `number` 字段加一event.on('add', () => {this.setState({number: this.state.number + 1});});}render() {return (<div className="m-show">{this.state.number}</div>);}}
Add组件出发操作加减的事件, Show组件监听事件实现状态更改
结语
这样介绍了组件通信常用的几种方式,以及通过 EventBus 实现组件之间扁平化通信。 本章以 React 框架举例,同时在其他主流的 MVVM 框架都适用(Vuejs,Angular等)。
