接上一节:https://www.jianshu.com/p/a97f5d408967
这次我们用一个共同继承遗产的例子,通过「eventHub」来完成「组件通讯」。
需求说明:我们在两个「爸爸组件」和四个「儿子组件」中点击消费,然后剩余的金额都能在其他组件中显示,组件通讯达到金额的「同步」。
按照上一节的方法通讯,比如我们在「Son2」点击消费,要通过「回调函数」通过其他组件。如下图,「红色箭头」表示信息传递方向。
现在我们换一种方式,我们“雇佣”一个管家,来专门来管理这笔钱,每一个组件想要消费钱,需要向这个管家报告,这个管家我们称为「eventHub」。「Son2」组件想要消费,「eventHub」得知后并修改金额,然后把新的金额告诉「App」组件,然后从顶端的「App」组件「向下单向」传递信息给其他组件。如下图所示:
代码:
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(
);
}
}
class BigDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
大爸:
{this.props.money.amount}
);
}
}
class LittleDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
小爸:
{this.props.money.amount}
);
}
}
class Son1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子1:
{this.props.money.amount}
);
}
}
class Son2 extends React.Component {
constructor(props) {
super(props);
}
// 消费
consume() {
// 发布事件
eventHub.trigger('consume', 100);
}
render() {
return(
儿子2:
{this.props.money.amount}
);
}
}
class Son3 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子3:
{this.props.money.amount}
);
}
}
class Son4 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子4:
{this.props.money.amount}
);
}
}
render();
function render() {
ReactDOM.render( , 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(
);
}
}
class BigDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
大爸:
{this.props.money.amount}
);
}
}
class LittleDad extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
小爸:
{this.props.money.amount}
);
}
}
class Son1 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子1:
{this.props.money.amount}
);
}
}
class Son2 extends React.Component {
constructor(props) {
super(props);
}
// 消费
consume() {
// 发布事件
// eventHub.trigger('consume', 100);
// 换用「Redux」
store.dispatch({ type: 'CONSUME', payload: 100});
}
render() {
return(
儿子2:
{this.props.money.amount}
);
}
}
class Son3 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子3:
{this.props.money.amount}
);
}
}
class Son4 extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
儿子4:
{this.props.money.amount}
);
}
}
store.subscribe(() => {
render();
})
render();
function render() {
ReactDOM.render(, document.querySelector('#root'));
}
如上述代码,其实就是「Redex」中多了几个API来达到跟「eventHub」一样的功能。
// store, 就是保存了所有数据的集合。
// dispatch,就是发送action,跟eventHub.trigger相似
// reducer,就是统一处理数据,跟eventHub.on相似
// subscribe,就是在store的状态有改变的时候,可以进行重新渲染页面