React 组件通信总结

React 组件通信总结

父子通信

  • 传递数据(父传子)与传递方法(子传父)

    /*
     * @Author: HuangBingQuan bingquan111@qq.com
     * @Date: 2022-11-21 16:02:17
     * @LastEditors: HuangBingQuan bingquan111@qq.com
     * @LastEditTime: 2022-11-21 16:48:31
     * @FilePath: /react_test/src/02-advanced/01-子传父.js
     * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
     */
    import React, { Component } from 'react'
    
    class Navbar extends Component {
      render() {
        return (
          <div style={{background: "red"}}>
            {/* <button onClick={()=> {
              let that = this.props.that;
              console.log(that.state.SidebarIsShow);
              that.setState({
                SidebarIsShow: !that.state.SidebarIsShow
              })
            }}>click</button> */}
            <button 
              onClick={()=> {
                // 子通知父,让父的SidebarIsShow 取反
                this.props.event() // 调用父组件传来的回调函数
              }}
            >
              click
            </button>
            <span>NavBar</span>
          </div>
        )
      }
    }
    
    class Sidebar extends Component {
      render() {
        return (
          <div style={{background: "yellow", width: "200px"}}>
            <ul>
              <li>111111</li>
              <li>111111</li>
              <li>111111</li>
              <li>111111</li>
              <li>111111</li>
              <li>111111</li>
            </ul>
          </div>
        )
      }
    }
    
    export default class App extends Component {
      state = {
        SidebarIsShow: false
      }
      render() {
        return (
          <div>
            {/* <Navbar that={this}></Navbar> */}
            {/*  */}
            <Navbar event={()=> {
              this.setState({
                SidebarIsShow: !this.state.SidebarIsShow
              })
            }}></Navbar>
    
            {/* <Sidebar></Sidebar> */}
            { this.state.SidebarIsShow && <Sidebar></Sidebar> }
          </div>
        )
      }
    }
    
    
  • ref标记(父组件拿到子组件的引用,从而调用子组件的方法)

    /*
     * @Author: HuangBingQuan bingquan111@qq.com
     * @Date: 2022-11-21 21:38:26
     * @LastEditors: HuangBingQuan bingquan111@qq.com
     * @LastEditTime: 2022-11-22 16:51:06
     * @FilePath: /react_test/src/02-advanced/04-父子通信版-表单域组件.js
     * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
     */
    import React, { Component } from 'react'
    
    class Filed extends Component {
      state = {
        val: ""
      }
      render() {
        return (
          <div style={{background: "yellow"}}>
            <label>{this.props.label}</label>
            <input type={this.props.type} value={this.state.val} onChange={(evt)=> {
              this.setState({
                val: evt.target.value
              })
            }}></input>
          </div>
        )
      }
      clear() {
        this.setState({
          val: ""
        })
      }
      setValue(value) {
        this.setState({
          val: value
        })
      }
    }
    
    export default class App extends Component {
      userName = React.createRef();
      password = React.createRef()
      render() {
        return (
          <div>
            <h1>登录页面</h1> 
            <Filed ref={this.userName} label="用户名" type="text" ></Filed>
            <Filed ref={this.password} label="密码" type="password"></Filed>
            <button onClick={()=> {
              console.log(this.userName.current);
              console.log(this.password.current);
              console.log(`账号:${this.userName.current.state.val}-密码:${this.password.current.state.val}`);
            }}>登录</button>
            <button onClick={()=> {
              this.userName.current.clear()
              this.password.current.clear()
            }}>取消</button>
            <div style={{background: "#ff2121"}}>
              <svg style={{width: "20px"}} t="1669106904741" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3653" width="200" height="200"><path d="M513.506307 974.330764c-62.755276 0-123.643018-12.295024-180.971701-36.543288-55.363935-23.416316-105.081267-56.935734-147.772578-99.626022-42.690288-42.690288-76.209706-92.408643-99.626022-147.771555-24.248264-57.328683-36.542264-118.216425-36.542264-180.971701s12.295024-123.643018 36.542264-180.972724c23.416316-55.364959 56.935734-105.08229 99.626022-147.773601s92.408643-76.210729 147.772578-99.628068c57.328683-24.248264 118.216425-36.543288 180.971701-36.543288 62.755276 0 123.643018 12.295024 180.972724 36.543288 55.364959 23.417339 105.08229 56.936757 147.773601 99.628068s76.211752 92.409666 99.628068 147.773601c24.248264 57.329706 36.543288 118.217449 36.543288 180.972724s-12.295024 123.643018-36.543288 180.971701c-23.417339 55.363935-56.93778 105.081267-99.628068 147.771555-42.691311 42.691311-92.409666 76.210729-147.773601 99.627045C637.150348 962.03574 576.262606 974.330764 513.506307 974.330764zM513.506307 82.074274c-57.69912 0-113.661689 11.296277-166.334329 33.5757-50.884924 21.522176-96.587825 52.338019-135.840828 91.591021-39.251979 39.251979-70.066799 84.955904-91.588975 135.841851-22.278399 52.67264-33.574676 108.636233-33.574676 166.335353s11.296277 113.662713 33.574676 166.334329c21.522176 50.885947 52.338019 96.588849 91.588975 135.839805 39.251979 39.251979 84.955904 70.067822 135.840828 91.589998 52.67264 22.278399 108.635209 33.574676 166.334329 33.574676s113.662713-11.295254 166.335353-33.574676c50.885947-21.522176 96.589872-52.338019 135.841851-91.589998 39.253002-39.250956 70.068845-84.955904 91.591021-135.839805 22.278399-52.67264 33.5757-108.635209 33.5757-166.334329 0-57.69912-11.296277-113.662713-33.5757-166.335353-21.522176-50.885947-52.338019-96.589872-91.591021-135.841851s-84.955904-70.068845-135.841851-91.591021C627.170043 93.370551 571.205427 82.074274 513.506307 82.074274z" p-id="3654"></path><path d="M507.742023 722.763215c-10.376325 0-18.786878-8.411577-18.786878-18.786878L488.955144 590.364789c0-73.891917 51.429323-99.112322 96.804766-121.363092 52.704362-25.845645 98.219999-48.165999 88.23867-139.822512-3.546779-32.550347-19.739577-57.901735-48.130184-75.352175-28.942169-17.788132-69.626777-26.617218-117.695562-25.511024-34.110889 0.781806-66.710354 10.963703-94.273107 29.447682-27.16264 18.215874-48.102554 43.559075-60.554144 73.290213-4.009314 9.56996-15.017018 14.07967-24.585955 10.07138-9.570983-4.00829-14.07967-15.015995-10.07138-24.585955 15.304568-36.540218 40.990576-67.654866 74.283844-89.981361 33.519418-22.478967 73.057923-34.859949 114.341165-35.806507 55.296397-1.2689 103.106286 9.476839 138.229225 31.064506 38.252209 23.51046 61.008492 59.228963 65.808822 103.294574 12.836353 117.857245-54.744835 150.998039-109.046578 177.627537-21.070898 10.332323-40.972157 20.091594-54.872748 33.641191-14.455223 14.089903-20.901029 30.739095-20.901029 53.986565L526.530948 703.976336C526.528901 714.351638 518.117324 722.763215 507.742023 722.763215z" p-id="3655"></path><path d="M531.058055 810.18631c0 10.721179-8.691963 19.413142-19.417235 19.413142-10.721179 0-19.413142-8.691963-19.413142-19.413142 0-10.725272 8.691963-19.417235 19.413142-19.417235C522.366092 790.768051 531.058055 799.461037 531.058055 810.18631z" p-id="3656"></path></svg>
            </div>
          </div>
        )
      }
    }
    
    

非父子组件通信

  • 状态提升(中间人模式)

    • React中的状态提升概括来说,就是将多个组件需要共享的状态提升到它们最近的父组件上,在父组件上改变这个状态然后通过props分发给子组件
    /*
     * @Author: HuangBingQuan bingquan111@qq.com
     * @Date: 2022-11-23 15:08:14
     * @LastEditors: HuangBingQuan bingquan111@qq.com
     * @LastEditTime: 2022-11-23 16:34:32
     * @FilePath: /react_test/src/02-advanced/06-中间人模式.js
     * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
     */
    import React, { Component } from 'react'
    import axios from 'axios';
    import './css/communinaion.scss'
    class FilmItem extends Component {
      render() {
        // console.log(this.props);
        let { name, poster, grade, synopsis, callback } = this.props;
        return (
          <div className='filmitem' onClick={(e)=> {
            callback(synopsis)
          }}>
            <img src={poster} alt={name}></img>
            <h4>{name}</h4>
            <div>观众评分:{grade}</div>
          </div>
        )
      }
    }
    
    class FilmDetail extends Component {
      render() {
        return (
          <div className='filmdetail'>{this.props.con}</div>
        )
      }
    }
    
    export default class App extends Component {
      constructor() {
        super();
        this.state = {
          filmList: [],
          con: ""
        }
        this.getData()();
      }
      getData() {
        return async()=> {
          let { data: { data: { films } } } = await axios({ url: "/test.json", method: "get" });
          console.log( films );
          this.setState({
            filmList: films
          })
        }
      }
      render() {
        return (
          <div>
            { 
              this.state.filmList.map(item =>
                <FilmItem key={item.filmId} {...item} callback={(value)=> {
                  this.setState({
                    con: value
                  })
                }}></FilmItem>
              )
            }
            <FilmDetail con={this.state.con}></FilmDetail>
          </div>
        )
      }
    }
    
    
  • 发布订阅模式实现

    /*
     * @Author: HuangBingQuan bingquan111@qq.com
     * @Date: 2022-11-23 15:08:14
     * @LastEditors: HuangBingQuan bingquan111@qq.com
     * @LastEditTime: 2022-11-23 18:54:31
     * @FilePath: /react_test/src/02-advanced/06-中间人模式.js
     * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
     */
    import React, { Component } from 'react'
    import axios from 'axios';
    import './css/communinaion.scss'
    
    // 调度中心
    var bus = {
      list: [],
      // 订阅
      subscribe(callback) {
        // console.log(callback);
        this.list.push(callback)
      },
      // 发布
      publish(text) {
        // 遍历注册集合,执行回调函数
        this.list.forEach(callback => {
          callback && callback(text)
        })
      }
    }
    
    class FilmItem extends Component {
      render() {
        // console.log(this.props);
        let { name, poster, grade, synopsis } = this.props;
        return (
          <div className='filmitem' onClick={(e)=> {
            bus.publish(synopsis)
          }}>
            <img src={poster} alt={name}></img>
            <h4>{name}</h4>
            <div>观众评分:{grade}</div>
          </div>
        )
      }
    }
    
    class FilmDetail extends Component {
      constructor() {
        super();
        this.state = {
          con: ""
        }
        bus.subscribe((con)=> {
          this.setState({
            con,
          })
        })
      }
      render() {
        return (
          <div className='filmdetail'>{this.state.con}</div>
        )
      }
    }
    
    export default class App extends Component {
      constructor() {
        super();
        this.state = {
          filmList: [],
        }
        this.getData()();
      }
      getData() {
        return async()=> {
          let { data: { data: { films } } } = await axios({ url: "/test.json", method: "get" });
          console.log( films );
          this.setState({
            filmList: films
          })
        }
      }
      render() {
        return (
          <div>
            { 
              this.state.filmList.map(item =>
                <FilmItem key={item.filmId} {...item} callback={(value)=> {
                  this.setState({
                    con: value
                  })
                }}></FilmItem>
              )
            }
            <FilmDetail></FilmDetail>
          </div>
        )
      }
    }
    
    
  • context状态数传参

    import React, { Component } from 'react'
    const GlobalContext = React.createContext()
    class App extends Component {
      constructor() {
        super();
        this.state = {
          info: ""
        }
      }
      render() {
        return (
        	// 供应数据
          <GlobalContext.Provider value={{
          	info: this.state.info,
          	changeInfo: (val)=> {
          		this.setState({
                info: val
              })
       			}
          }}>
          	<Test></Test>
          </GlobalContext.Provider>
        )
      }
    }
    
    class Test extends Component {
      render() {
        return (
        	// 消费数据
          <GlobalContext.Consumer>
          	{ 
              (value)=> {
          			return (
                	<div>{value.info}</div>
                )
        			}
      			}
          </GlobalContext.Consumer>
        )
      }
    } 
    
posted @ 2022-11-23 21:10  HuangBingQuan  阅读(39)  评论(0编辑  收藏  举报