美文网首页
2. 组件通信(父子/爷孙)

2. 组件通信(父子/爷孙)

作者: Jason_Shu | 来源:发表于2019-01-25 19:44 被阅读0次

    今天我们通过「龟兔赛跑」的故事,来理解React中的组件通讯。

    class App extends React.Component{
      constructor(props) {
        super(props);
        this.state = {
          allTime1: 0, // 兔子跑完全程所用时间
          allTime2: 0, // 乌龟跑完全程所用时间
        }
        
        this.startTime = new Date();  // 记录开始时间
      }
      
      success1() {
        this.setState({
          allTime1: new Date() - this.startTime
        });
      }
      
      success2() {
        this.setState({
          allTime2: new Date() - this.startTime
        });
      }
      
      render() {
        return(
          <div>
            <div className="time-wrapper">
              <Time1 time={this.state.allTime1}/>
              <Time2 time={this.state.allTime2}/>
            </div>
            <Track1 success={this.success1.bind(this)}/>
            <Track2 success={this.success2.bind(this)}/>
            
          </div>
        );
      }
    }
    
    // 记录兔子用时组件
    class Time1 extends React.Component {
      constructor(props) {
        super(props);
      }
      
      render() {
        return(
          <div className="rabbit">
            <span>🐇</span>
            <span>{this.props.time}</span>
          </div>
        );
      }
    }
    
    // 记录乌龟用时组件
    class Time2 extends React.Component {
      constructor(props) {
        super(props);
      }
      
      render() {
        return(
          <div className="tortoise">
            <span>🐢</span>
            <span>{this.props.time}</span>
          </div>
        );
      }
    }
    
    
    class Track1 extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          style: {
            transform: 'translateX(0%)'
          }
        };
        
        // 初试位置
        let position = 0;
        
        // 计时器
        let time = setInterval(() => {
          position += 30;
          
          if(position >= 100) {
            position = 100;
            clearInterval(time);
            this.props.success();
          }
          this.setState({
            style: {
              transform: `translateX(${position}%)`
            }
          });
        }, 1000);
      }
      render() {
        return(
          <div className="track-wrapper">
            <div style={this.state.style}>🐇</div>
            <div className="track"></div>
          </div>
        );
      }
    }
    
    class Track2 extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          style: {
            transform: 'translateX(0%)'
          }
        };
        
        // 初试位置
        let position = 0;
        
        // 计时器
        let time = setInterval(() => {
          position += 20;
          
          if(position >= 100) {
            position = 100;
            clearInterval(time);
          
            this.props.success();
          }
          this.setState({
            style: {
              transform: `translateX(${position}%)`
            }
          });
        }, 1000);
      }
      render() {
        return(
          <div className="track-wrapper">
            <div style={this.state.style}>🐢</div>
            <div className="track"></div>
          </div>
        );
      }
    }
    
    render();
    
    function render() {
      ReactDOM.render(<App/>, document.querySelector('#root'));
    }
    
    父子组件结构图.png 起始状态.png 结束状态.png

    如上图,是组件之间的结构图,相当于一棵「树结构」。首先在「Track1」和「Track2」中执行由「App」传给他俩的「success」回调函数来记录所花时间,「App」中的state保存了「Track1」和「Track2」中执行的时间,然后传到「Time1」和「Time2」中,「Time1」和「Time2」通过「props」拿到时间渲染到组件内。

    image.png

    以上图「Track2」为例,当「Track2」中的乌龟跑到终点后,便调用「success」函数(图中1处),这个函数是由「App」组件传给「Track2」的,可以通知「App」乌龟跑完所需要的时间,记录到「Track2」的「this.state」里。再由「App」将「this.state」里面记录的时间传给「Time2」(图中2处)。

    我再「Track1」和「Trank2」组件上加一层「PlayGround」组件。

    class App extends React.Component{
      constructor(props) {
        super(props);
        this.state = {
          allTime1: 0, // 兔子跑完全程所用时间
          allTime2: 0, // 乌龟跑完全程所用时间
        }
        
        this.startTime = new Date();  // 记录开始时间
      }
      
      success1() {
        this.setState({
          allTime1: new Date() - this.startTime
        });
      }
      
      success2() {
        this.setState({
          allTime2: new Date() - this.startTime
        });
      }
      
      render() {
        return(
          <div>
            <div className="time-wrapper">
              <Time1 time={this.state.allTime1}/>
              <Time2 time={this.state.allTime2}/>
            </div>
            <PlayGround 
              success1={this.success1.bind(this)}
              success2={this.success2.bind(this)}
              />
            
          </div>
        );
      }
    }
    
    // 记录兔子用时组件
    class Time1 extends React.Component {
      constructor(props) {
        super(props);
      }
      
      render() {
        return(
          <div className="rabbit">
            <span>🐇</span>
            <span>{this.props.time}</span>
          </div>
        );
      }
    }
    
    // 记录乌龟用时组件
    class Time2 extends React.Component {
      constructor(props) {
        super(props);
      }
      
      render() {
        return(
          <div className="tortoise">
            <span>🐢</span>
            <span>{this.props.time}</span>
          </div>
        );
      }
    }
    
    
    class Track1 extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          style: {
            transform: 'translateX(0%)'
          }
        };
        
        // 初试位置
        let position = 0;
        
        // 计时器
        let time = setInterval(() => {
          position += 30;
          
          if(position >= 100) {
            position = 100;
            clearInterval(time);
            this.props.success();
          }
          this.setState({
            style: {
              transform: `translateX(${position}%)`
            }
          });
        }, 1000);
      }
      render() {
        return(
          <div className="track-wrapper">
            <div style={this.state.style}>🐇</div>
            <div className="track"></div>
          </div>
        );
      }
    }
    
    class Track2 extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          style: {
            transform: 'translateX(0%)'
          }
        };
        
        // 初试位置
        let position = 0;
        
        // 计时器
        let time = setInterval(() => {
          position += 20;
          
          if(position >= 100) {
            position = 100;
            clearInterval(time);
          
            this.props.success();
          }
          this.setState({
            style: {
              transform: `translateX(${position}%)`
            }
          });
        }, 1000);
      }
      render() {
        return(
          <div className="track-wrapper">
            <div style={this.state.style}>🐢</div>
            <div className="track"></div>
          </div>
        );
      }
    }
    
    class PlayGround extends React.Component {
      constructor(props) {
        super(props);
      }
      render() {
        return( 
          <div className='playground'>
            <Track1 success={this.props.success1}/>
            <Track2 success={this.props.success2}/>
          </div>
        )
      }
    }
    
    render();
    
    function render() {
      ReactDOM.render(<App/>, document.querySelector('#root'));
    }
    
    爷孙组件结构图.png

    跟上面的功能相似,还是「App」把回调函数「success」传到「PlayGround」组件,再由「PlayGround」组件传到「Track1」和「Track2」,「Track1」和「Track2」中调用「success」函数把时间记录在「App」中,然后把记录的时间从「App」中传到「Time1」和「Time2」。

    相关文章

      网友评论

          本文标题:2. 组件通信(父子/爷孙)

          本文链接:https://www.haomeiwen.com/subject/bhvmjqtx.html