场景

现在有一个家庭,他们有10w的财产。家庭成员分别有爸爸1、爸爸2。他们分别有两个孩子,儿子11、儿子12、儿子21、儿子22。现在要实现家族中每位成员花费金额时,其他成员都需要知道。

方法一 eventHub(非单项数据流)

找个跑腿的。在每次消费后去通知另一位成员。

代码

HTML

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.0-rc.0/umd/react.production.min.js"></script>
  10. <script
  11. src="https://cdn.bootcdn.net/ajax/libs/react-dom/0.0.0-0c756fb-f7f79fd/umd/react-dom.production.min.js"></script>
  12. </head>
  13. <body>
  14. <div id="root"></div>
  15. </body>
  16. </html>

CSS

  1. * {
  2. box-sizing: border-box;
  3. margin: 0;
  4. padding: 0;
  5. }
  6. .home {
  7. display: flex;
  8. justify-content: center;
  9. align-items: center;
  10. padding: 10px;
  11. color: #fff;
  12. background: #000;
  13. }
  14. .father {
  15. padding: 10px;
  16. margin-top: 10px;
  17. border: 1px solid #fff;
  18. }
  19. .son {
  20. padding: 10px;
  21. margin: 10px 0;
  22. border: 1px solid #fff;
  23. }

JSX

  1. // 财产
  2. let money = {
  3. amount: 100000
  4. }
  5. // 跑腿需要监听的事件
  6. let fnLists = {}
  7. let eventHub = {
  8. trigger(eventName, data) {
  9. let fnList = fnLists[eventName]
  10. if (!fnList) return
  11. for (let i = 0; i < fnList.length; i++) {
  12. fnList[i](data)
  13. }
  14. },
  15. on(eventName, fn) {
  16. if (!fnLists[eventName]) {
  17. fnLists[eventName] = []
  18. }
  19. fnLists[eventName].push(fn)
  20. }
  21. }
  22. class App extends React.Component {
  23. constructor() {
  24. super()
  25. this.state = {
  26. money: money
  27. }
  28. }
  29. render() {
  30. return (
  31. <div className="home">
  32. <Father1 money={this.state.money}/>
  33. <Father2 money={this.state.money}/>
  34. </div>
  35. )
  36. }
  37. }
  38. class Father1 extends React.Component {
  39. constructor() {
  40. super()
  41. this.state = {
  42. money: money
  43. }
  44. }
  45. render() {
  46. return (
  47. <div className="father">
  48. Father1 {this.state.money.amount}
  49. <Son11 money={this.state.money}/>
  50. <Son12 money={this.state.money}/>
  51. </div>
  52. )
  53. }
  54. }
  55. class Son11 extends React.Component {
  56. constructor() {
  57. super()
  58. this.state = {
  59. money: money
  60. }
  61. }
  62. render() {
  63. return (
  64. <div className="son">
  65. son11 {this.state.money.amount}
  66. </div>
  67. )
  68. }
  69. }
  70. class Son12 extends React.Component {
  71. constructor() {
  72. super()
  73. this.state = {
  74. money: money
  75. }
  76. // 监听别人是否花钱
  77. eventHub.on("我想花钱", (data)=>{
  78. this.setState({
  79. money: money
  80. })
  81. })
  82. }
  83. // 通知跑腿需要花钱
  84. x() {
  85. money.amount -= 100
  86. eventHub.trigger("我想花钱", 100)
  87. this.setState({
  88. money: money
  89. })
  90. }
  91. render() {
  92. return (
  93. <div className="son">
  94. son12 {this.state.money.amount}
  95. <button onClick={() => this.x()}>花钱</button>
  96. </div>
  97. )
  98. }
  99. }
  100. class Father2 extends React.Component {
  101. constructor() {
  102. super()
  103. }
  104. render() {
  105. return (
  106. <div className="father">
  107. Father2 {this.props.money.amount}
  108. <Son21 money={this.props.money}/>
  109. <Son22 money={this.props.money}/>
  110. </div>
  111. )
  112. }
  113. }
  114. class Son21 extends React.Component {
  115. constructor() {
  116. super()
  117. }
  118. render() {
  119. return (
  120. <div className="son">
  121. son21 {this.props.money.amount}
  122. </div>
  123. )
  124. }
  125. }
  126. class Son22 extends React.Component {
  127. constructor() {
  128. super()
  129. // 监听别人是否花钱
  130. eventHub.on("我想花钱", (data)=>{
  131. this.setState({
  132. money: money
  133. })
  134. })
  135. }
  136. // 通知跑腿需要花钱
  137. x(){
  138. money.amount -= 100
  139. eventHub.trigger("我想花钱", 100)
  140. this.setState({
  141. money: money
  142. })
  143. }
  144. render() {
  145. return (
  146. <div className="son">
  147. son22 {this.props.money.amount}
  148. <button onClick={()=>this.x()}>花钱</button>
  149. </div>
  150. )
  151. }
  152. }
  153. render()
  154. function render() {
  155. ReactDOM.render(<App/>, document.querySelector("#root"))
  156. }

解析

代码预览

提前跟跑腿的说明,每当son22花钱时,通知son11有人花钱了。从而更新信息。

每个人消费跑腿都需要来回通知效率很慢。需要实现告诉跑腿的要监听谁消费了。

方法二 eventHub(单向数据流)

找一个管家,每次消费都去向下通知所有成员。

代码

HTML

与上次一样的代码,这里就不重复了

CSS

与上次一样的代码,这里就不重复了

JSX

  1. // 财产
  2. let money = {
  3. amount: 100000
  4. }
  5. // 事件中心
  6. let fnLists = {}
  7. let eventHub = {
  8. trigger(eventName, data) {
  9. let fnList = fnLists[eventName]
  10. if (!fnList) return
  11. for (let i = 0; i < fnList.length; i++) {
  12. fnList[i](data)
  13. }
  14. },
  15. on(eventName, fn) {
  16. if (!fnLists[eventName]) {
  17. fnLists[eventName] = []
  18. }
  19. fnLists[eventName].push(fn)
  20. }
  21. }
  22. // 管家
  23. let x = {
  24. init() {
  25. eventHub.on("我想花钱", function (data) {
  26. money.amount -= data
  27. render()
  28. })
  29. }
  30. }
  31. x.init()
  32. class App extends React.Component {
  33. constructor() {
  34. super()
  35. this.state = {
  36. money: money
  37. }
  38. }
  39. render() {
  40. return (
  41. <div className="home">
  42. <Father1 money={this.state.money}/>
  43. <Father2 money={this.state.money}/>
  44. </div>
  45. )
  46. }
  47. }
  48. class Father1 extends React.Component {
  49. constructor() {
  50. super()
  51. }
  52. render() {
  53. return (
  54. <div className="father">
  55. Father1 {this.props.money.amount}
  56. <Son11 money={this.props.money}/>
  57. <Son12 money={this.props.money}/>
  58. </div>
  59. )
  60. }
  61. }
  62. class Son11 extends React.Component {
  63. constructor() {
  64. super()
  65. }
  66. render() {
  67. return (
  68. <div className="son">
  69. son11 {this.props.money.amount}
  70. </div>
  71. )
  72. }
  73. }
  74. class Son12 extends React.Component {
  75. constructor() {
  76. super()
  77. }
  78. x() {
  79. eventHub.trigger("我想花钱", 100)
  80. }
  81. render() {
  82. return (
  83. <div className="son">
  84. son12 {this.props.money.amount}
  85. <button onClick={() => this.x()}>花钱</button>
  86. </div>
  87. )
  88. }
  89. }
  90. class Father2 extends React.Component {
  91. constructor() {
  92. super()
  93. }
  94. render() {
  95. return (
  96. <div className="father">
  97. Father2 {this.props.money.amount}
  98. <Son21 money={this.props.money}/>
  99. <Son22 money={this.props.money}/>
  100. </div>
  101. )
  102. }
  103. }
  104. class Son21 extends React.Component {
  105. constructor() {
  106. super()
  107. }
  108. render() {
  109. return (
  110. <div className="son">
  111. son21 {this.props.money.amount}
  112. </div>
  113. )
  114. }
  115. }
  116. class Son22 extends React.Component {
  117. constructor() {
  118. super()
  119. }
  120. render() {
  121. return (
  122. <div className="son">
  123. son22 {this.props.money.amount}
  124. </div>
  125. )
  126. }
  127. }
  128. render()
  129. function render() {
  130. ReactDOM.render(<App/>, document.querySelector("#root"))
  131. }

解析

预览地址

全部数据统一由管家来下发更新

方法三 redux(单向数据流)

与eventHub的思路一样

HTML

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.0-rc.0/umd/react.production.min.js"></script>
  10. <script
  11. src="https://cdn.bootcdn.net/ajax/libs/react-dom/0.0.0-0c756fb-f7f79fd/umd/react-dom.production.min.js"></script>
  12. <script src="https://cdn.bootcdn.net/ajax/libs/redux/4.0.5/redux.min.js"></script>
  13. </head>
  14. <body>
  15. <div id="root"></div>
  16. </body>
  17. </html>

CSS

与上次一样的代码,这里就不重复了

JSX

  1. // redux
  2. let createStore = Redux.createStore
  3. let reducers = (state, action) => {
  4. state = state || {
  5. money: {amount: 100000}
  6. }
  7. switch (action.type) {
  8. case "我想花钱":
  9. return {
  10. money: {
  11. amount: state.money.amount - action.payload
  12. }
  13. }
  14. default:
  15. return state
  16. }
  17. }
  18. const store = createStore(reducers)
  19. class App extends React.Component {
  20. constructor() {
  21. super()
  22. }
  23. render() {
  24. return (
  25. <div className="home">
  26. <Father1 money={this.props.store.money}/>
  27. <Father2 money={this.props.store.money}/>
  28. </div>
  29. )
  30. }
  31. }
  32. class Father1 extends React.Component {
  33. constructor() {
  34. super()
  35. }
  36. render() {
  37. return (
  38. <div className="father">
  39. Father1 {this.props.money.amount}
  40. <Son11 money={this.props.money}/>
  41. <Son12 money={this.props.money}/>
  42. </div>
  43. )
  44. }
  45. }
  46. class Son11 extends React.Component {
  47. constructor() {
  48. super()
  49. }
  50. render() {
  51. return (
  52. <div className="son">
  53. son11 {this.props.money.amount}
  54. </div>
  55. )
  56. }
  57. }
  58. class Son12 extends React.Component {
  59. constructor() {
  60. super()
  61. }
  62. x() {
  63. store.dispatch({type: "我想花钱", payload: 100})
  64. }
  65. render() {
  66. return (
  67. <div className="son">
  68. son12 {this.props.money.amount}
  69. <button onClick={() => this.x()}>花钱</button>
  70. </div>
  71. )
  72. }
  73. }
  74. class Father2 extends React.Component {
  75. constructor() {
  76. super()
  77. }
  78. render() {
  79. return (
  80. <div className="father">
  81. Father2 {this.props.money.amount}
  82. <Son21 money={this.props.money}/>
  83. <Son22 money={this.props.money}/>
  84. </div>
  85. )
  86. }
  87. }
  88. class Son21 extends React.Component {
  89. constructor() {
  90. super()
  91. }
  92. render() {
  93. return (
  94. <div className="son">
  95. son21 {this.props.money.amount}
  96. </div>
  97. )
  98. }
  99. }
  100. class Son22 extends React.Component {
  101. constructor() {
  102. super()
  103. }
  104. render() {
  105. return (
  106. <div className="son">
  107. son22 {this.props.money.amount}
  108. </div>
  109. )
  110. }
  111. }
  112. function render() {
  113. ReactDOM.render(<App store={store.getState()}/>, document.querySelector("#root"))
  114. }
  115. render()
  116. store.subscribe(render)