接上一节:https://www.jianshu.com/p/a97f5d408967
这次我们用一个共同继承遗产的例子,通过「eventHub」来完成「组件通讯」。
需求说明:我们在两个「爸爸组件」和四个「儿子组件」中点击消费,然后剩余的金额都能在其他组件中显示,组件通讯达到金额的「同步」。
![](https://img.haomeiwen.com/i13186984/003826fafa5193d9.png)
按照上一节的方法通讯,比如我们在「Son2」点击消费,要通过「回调函数」通过其他组件。如下图,「红色箭头」表示信息传递方向。
![](https://img.haomeiwen.com/i13186984/7e9eebe4a53da262.png)
现在我们换一种方式,我们“雇佣”一个管家,来专门来管理这笔钱,每一个组件想要消费钱,需要向这个管家报告,这个管家我们称为「eventHub」。「Son2」组件想要消费,「eventHub」得知后并修改金额,然后把新的金额告诉「App」组件,然后从顶端的「App」组件「向下单向」传递信息给其他组件。如下图所示:
![](https://img.haomeiwen.com/i13186984/7ef5e31682d36a29.png)
代码:
var money = {
amount: 10000
};
var eventHub = {
events: {},
trigger(eventName, data) {
var fnList = this.events[eventName];
for(let i = 0; i < fnList.length; i++) {
fnList[i].call(undefined, data);
}
},
on(eventName, fn) {
if(!(eventName in this.events)) {
this.events[eventName] = [];
}
console.log('this is on')
this.events[eventName].push(fn);
}
};
var init = () => {
// 订阅事件
eventHub.on('consume', (data) => {
money.amount -= data;
// 修改money后再次render
render();
})
};
init();
class App extends React.Component {
constructor() {
super();
this.state = {
money: money
};
}
render() {
return(
<div className="app-wrapper">
<BigDad money={this.state.money}/>
<LittleDad money={this.state.money}/>
</div>
);
}
}
class BigDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="bigDad">
<span>大爸:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
<Son1 money={this.props.money}/>
<Son2 money={this.props.money}/>
</div>
);
}
}
class LittleDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="littleDad">
<span>小爸:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
<Son3 money={this.props.money}/>
<Son4 money={this.props.money}/>
</div>
);
}
}
class Son1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son1">
<span>儿子1:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
class Son2 extends React.Component {
constructor(props) {
super(props);
}
// 消费
consume() {
// 发布事件
eventHub.trigger('consume', 100);
}
render() {
return(
<div className="son2">
<span>儿子2:</span>
<span className="amount">{this.props.money.amount}</span>
<button onClick={this.consume.bind(this)}>消费</button>
</div>
);
}
}
class Son3 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son3">
<span>儿子3:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
class Son4 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son4">
<span>儿子4:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
render();
function render() {
ReactDOM.render(<App/>, document.querySelector('#root'));
}
然后我们引入「Redux」来代替「eventHub」。
let createStore = Redux.createStore;
var money = {
amount: 10000
};
let store = createStore(reducer);
function reducer(state, action) {
if(typeof state === "undefined") {
state = money;
}
switch (action.type) {
case 'CONSUME':
return {
amount: state.amount - action.payload
}
default:
return state
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
money: money,
}
}
render() {
return(
<div className="app-wrapper">
<BigDad money={this.props.store}/>
<LittleDad money={this.props.store}/>
</div>
);
}
}
class BigDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="bigDad">
<span>大爸:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
<Son1 money={this.props.money}/>
<Son2 money={this.props.money}/>
</div>
);
}
}
class LittleDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="littleDad">
<span>小爸:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
<Son3 money={this.props.money}/>
<Son4 money={this.props.money}/>
</div>
);
}
}
class Son1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son1">
<span>儿子1:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
class Son2 extends React.Component {
constructor(props) {
super(props);
}
// 消费
consume() {
// 发布事件
// eventHub.trigger('consume', 100);
// 换用「Redux」
store.dispatch({ type: 'CONSUME', payload: 100});
}
render() {
return(
<div className="son2">
<span>儿子2:</span>
<span className="amount">{this.props.money.amount}</span>
<button onClick={this.consume.bind(this)}>消费</button>
</div>
);
}
}
class Son3 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son3">
<span>儿子3:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
class Son4 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="son4">
<span>儿子4:</span>
<span className="amount">{this.props.money.amount}</span>
<button>消费</button>
</div>
);
}
}
store.subscribe(() => {
render();
})
render();
function render() {
ReactDOM.render(<App store={store.getState()}/>, document.querySelector('#root'));
}
如上述代码,其实就是「Redex」中多了几个API来达到跟「eventHub」一样的功能。
// store, 就是保存了所有数据的集合。
// dispatch,就是发送action,跟eventHub.trigger相似
// reducer,就是统一处理数据,跟eventHub.on相似
// subscribe,就是在store的状态有改变的时候,可以进行重新渲染页面
网友评论