场景
现在有一个家庭,他们有10w的财产。家庭成员分别有爸爸1、爸爸2。他们分别有两个孩子,儿子11、儿子12、儿子21、儿子22。现在要实现家族中每位成员花费金额时,其他成员都需要知道。
方法一 eventHub(非单项数据流)
找个跑腿的。在每次消费后去通知另一位成员。
代码
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.0-rc.0/umd/react.production.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/0.0.0-0c756fb-f7f79fd/umd/react-dom.production.min.js"></script> </head> <body> <div id="root"></div> </body> </html>
|
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| * { box-sizing: border-box; margin: 0; padding: 0; }
.home { display: flex; justify-content: center; align-items: center; padding: 10px; color: #fff; background: #000; }
.father { padding: 10px; margin-top: 10px; border: 1px solid #fff; }
.son { padding: 10px; margin: 10px 0; border: 1px solid #fff; }
|
JSX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| let money = { amount: 100000 }
let fnLists = {} let eventHub = { trigger(eventName, data) { let fnList = fnLists[eventName] if (!fnList) return for (let i = 0; i < fnList.length; i++) { fnList[i](data) } }, on(eventName, fn) { if (!fnLists[eventName]) { fnLists[eventName] = [] } fnLists[eventName].push(fn) } }
class App extends React.Component { constructor() { super() this.state = { money: money } }
render() { return ( <div className="home"> <Father1 money={this.state.money}/> <Father2 money={this.state.money}/> </div> ) } }
class Father1 extends React.Component { constructor() { super() this.state = { money: money } }
render() { return ( <div className="father"> Father1 {this.state.money.amount} <Son11 money={this.state.money}/> <Son12 money={this.state.money}/> </div> ) } }
class Son11 extends React.Component { constructor() { super() this.state = { money: money } }
render() { return ( <div className="son"> son11 {this.state.money.amount} </div> ) } }
class Son12 extends React.Component { constructor() { super() this.state = { money: money } eventHub.on("我想花钱", (data)=>{ this.setState({ money: money }) }) } x() { money.amount -= 100 eventHub.trigger("我想花钱", 100) this.setState({ money: money }) }
render() { return ( <div className="son"> son12 {this.state.money.amount} <button onClick={() => this.x()}>花钱</button> </div> ) } }
class Father2 extends React.Component { constructor() { super() }
render() { return ( <div className="father"> Father2 {this.props.money.amount} <Son21 money={this.props.money}/> <Son22 money={this.props.money}/> </div> ) } }
class Son21 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son21 {this.props.money.amount} </div> ) } }
class Son22 extends React.Component { constructor() { super() eventHub.on("我想花钱", (data)=>{ this.setState({ money: money }) }) } x(){ money.amount -= 100 eventHub.trigger("我想花钱", 100) this.setState({ money: money }) } render() { return ( <div className="son"> son22 {this.props.money.amount} <button onClick={()=>this.x()}>花钱</button> </div> ) } }
render()
function render() { ReactDOM.render(<App/>, document.querySelector("#root")) }
|
解析
代码预览
提前跟跑腿的说明,每当son22花钱时,通知son11有人花钱了。从而更新信息。
每个人消费跑腿都需要来回通知效率很慢。需要实现告诉跑腿的要监听谁消费了。
方法二 eventHub(单向数据流)
找一个管家,每次消费都去向下通知所有成员。
代码
HTML
与上次一样的代码,这里就不重复了
CSS
与上次一样的代码,这里就不重复了
JSX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| let money = { amount: 100000 }
let fnLists = {} let eventHub = { trigger(eventName, data) { let fnList = fnLists[eventName] if (!fnList) return for (let i = 0; i < fnList.length; i++) { fnList[i](data) } }, on(eventName, fn) { if (!fnLists[eventName]) { fnLists[eventName] = [] } fnLists[eventName].push(fn) } }
let x = { init() { eventHub.on("我想花钱", function (data) { money.amount -= data render() }) } }
x.init()
class App extends React.Component { constructor() { super() this.state = { money: money } }
render() { return ( <div className="home"> <Father1 money={this.state.money}/> <Father2 money={this.state.money}/> </div> ) } }
class Father1 extends React.Component { constructor() { super() }
render() { return ( <div className="father"> Father1 {this.props.money.amount} <Son11 money={this.props.money}/> <Son12 money={this.props.money}/> </div> ) } }
class Son11 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son11 {this.props.money.amount} </div> ) } }
class Son12 extends React.Component { constructor() { super() }
x() { eventHub.trigger("我想花钱", 100) }
render() { return ( <div className="son"> son12 {this.props.money.amount} <button onClick={() => this.x()}>花钱</button> </div> ) } }
class Father2 extends React.Component { constructor() { super() }
render() { return ( <div className="father"> Father2 {this.props.money.amount} <Son21 money={this.props.money}/> <Son22 money={this.props.money}/> </div> ) } }
class Son21 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son21 {this.props.money.amount} </div> ) } }
class Son22 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son22 {this.props.money.amount} </div> ) } }
render()
function render() { ReactDOM.render(<App/>, document.querySelector("#root")) }
|
解析
预览地址
全部数据统一由管家来下发更新
方法三 redux(单向数据流)
与eventHub的思路一样
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.0-rc.0/umd/react.production.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/0.0.0-0c756fb-f7f79fd/umd/react-dom.production.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/redux/4.0.5/redux.min.js"></script> </head> <body> <div id="root"></div> </body> </html>
|
CSS
与上次一样的代码,这里就不重复了
JSX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| let createStore = Redux.createStore let reducers = (state, action) => { state = state || { money: {amount: 100000} } switch (action.type) { case "我想花钱": return { money: { amount: state.money.amount - action.payload } } default: return state } }
const store = createStore(reducers)
class App extends React.Component { constructor() { super() }
render() { return ( <div className="home"> <Father1 money={this.props.store.money}/> <Father2 money={this.props.store.money}/> </div> ) } }
class Father1 extends React.Component { constructor() { super() }
render() { return ( <div className="father"> Father1 {this.props.money.amount} <Son11 money={this.props.money}/> <Son12 money={this.props.money}/> </div> ) } }
class Son11 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son11 {this.props.money.amount} </div> ) } }
class Son12 extends React.Component { constructor() { super() }
x() { store.dispatch({type: "我想花钱", payload: 100}) }
render() { return ( <div className="son"> son12 {this.props.money.amount} <button onClick={() => this.x()}>花钱</button> </div> ) } }
class Father2 extends React.Component { constructor() { super() }
render() { return ( <div className="father"> Father2 {this.props.money.amount} <Son21 money={this.props.money}/> <Son22 money={this.props.money}/> </div> ) } }
class Son21 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son21 {this.props.money.amount} </div> ) } }
class Son22 extends React.Component { constructor() { super() }
render() { return ( <div className="son"> son22 {this.props.money.amount} </div> ) } }
function render() { ReactDOM.render(<App store={store.getState()}/>, document.querySelector("#root")) }
render() store.subscribe(render)
|