美文网首页爱编程
RN(四)--组件间通信

RN(四)--组件间通信

作者: doudo | 来源:发表于2018-01-03 18:14 被阅读88次

    谈组件通信前我们先了解一下组件的生命周期,这也是基础。

    一、组件生命周期

    我们先来看个图: 组件生命周期

    这个图看上图挺乱,其实我们注意一下经常会用到的就行:

    • render中只做与渲染有关的操作,只读取数据,不修改数据

    因为界面是经常变化的,render也是经常触发的。所以如果有修改数据的操作,就会多次触发,使结果难以预料。比如如果你在render中setState,就会触发render执行,而又会执行setState,导致死循环。

    • 随组件加载只执行一次的操作,应该放在componentWillMount和componentDidMount中。如从网络获取首页数据,如果需要用到timer定时器的时候可以在这里初始化定时器。
    • 记得在componentWillUnmount销毁定时器和一些订阅事件。
    • props发生变化时,会触发componentWillReceiveProps,经常会在这个方法中将变动同步给state。

    二、组件间通信

    1. 父组件向子组件通信(子组件间通信也类似)
    • 父组件以自身的state作为子组件的props。父组件调用setState修改state,触发父组件的render方法,于是子组件的props发生变化,此时子组件的生命周期方法componentWillReceiveProps会执行,在该方法中执行相应操作。
      看代码就容易理解了:
    //代码解释:父组件初始化一个时间time,父组件显示该值,并把这个初始值传给子组件显示;然后触摸会修改父组件的time值,并同步给子组件。
    //子组件
    class CountDown extends Component {
      state = {
        count: this.props.defaultTime,//state可以理解为静态,只初始化一次
      };
      render() {
        const { count } = this.state;
        return (  
          <Text>子:{this.state.count}</Text>
        )
      }
      componentWillReceiveProps(nextProps){
        this.setState({
          count : nextProps.defaultTime,
        });
      }
      componentWillUnmount() {
        clearInterval(this.timer);
      }
    }
    //父组件
    class App extends Component {
      state = {
        time : 30,
      }
      press = ()=>{
        const {time} = this.state;
        this.setState({
          time : time+10,
        })
      }
      
      render() {
        return (
          <View>
            <TouchableOpacity onPress={this.press}>
            <Text>加10秒</Text>
            </TouchableOpacity>
            
            <CountDown defaultTime={this.state.time} />{/*render刷新时,会重用该组件*/}
            <Text>父:{this.state.time}</Text>
          </View>
        )
      }
    }
    
    • 使用ref调用子组件的方法

    通过父组件通过ref将子组件的实例保存为父组件的成员变量,父组件就可以通过该成员变量直接执行子组件的方法了,可以把数据作为参数进行传递。ref后的参数即箭头函数的参数为该组件的实例。

    class CountDown extends Component {
      state = {
        count: this.props.defaultTime,//state可以理解为静态,只初始化一次
      };
      render() {
        const { count } = this.state;
        return (  
          <Text>子:{this.state.count}</Text>
        )
      }
      addTime = ()=>{
        const {count} = this.state;
        this.setState({
          count : count+10,
        })
      }
    }
    
    class App extends Component {
      state = {
        time : 30,
      }
      press = ()=>{
        //父组件自身数据的修改
        const {time} = this.state;
        this.setState({
          time : time+10,
        })
        //直接调用子组件的方法
        this.countDown.addTime(10);
      }
      
      render() {
        return (
          <View>
            <TouchableOpacity onPress={this.press}>
            <Text>加10秒</Text>
            </TouchableOpacity>
            
            {/*ref后的参数为该组件的实例*/}
            <CountDown ref={ins=>this.countDown=ins} defaultTime={this.state.time} />
            <Text>父:{this.state.time}</Text>
          </View>
        )
      }
    }
    
    2. 子组件向父组件通信(回调函数)

    父组件将函数作为子组件的props传递给子组件,子组件需要向父组件通信时,就调用传递过来的函数,数据作为函数的参数传回。

    //子组件
    class CountDown extends Component {
      state = {
        count: 5,
      };
      render() {
        const { count } = this.state;
        return (
            <Text>{count}</Text>
        )
      }
      componentDidMount() {
        this.timer = setInterval(() => {
          const { count } = this.state;
          if (count === 0) {
            this.props.timeUp && this.props.timeUp('aaa');//回调父组件的方法
            return clearInterval(this.timer);
          }
          this.setState({
            count: count - 1,
          });
        }, 1000);
      }
      componentWillUnmount() {
        clearInterval(this.timer);
      }
    }
    //父组件
    class App extends Component {
      timeUpParent = (param)=>{
        alert('时间到,参数:是'+param);
      }
      
      render() {
        return (
          <View>
            <CountDown timeUp={this.timeUpParent} />
          </View>
        )
      }
    
    }
    

    如果有多个子组件都会回调那怎么办呢?
    那就需要给每个子组件传个参数,不过子组件并不用显式的回传,只需传自己的要传的参数,父组件在参数中就会收到之前自己传的值。这样说可能不好理解,不要紧,看代码就好理解了。

    //子组件
    class CountDown extends Component {
      state = {
        count: 5,
      };
      render() {
        const { count } = this.state;
        return (
            <Text>{count}</Text>
        )
      }
      componentDidMount() {
        this.timer = setInterval(() => {
          const { count } = this.state;
          if (count === 0) {
            this.props.timeUp && this.props.timeUp('子组件传递的参数:aaa');//对于子组件来说,他要传的参数是箭头函数前边的参数
            return clearInterval(this.timer);
          }
          this.setState({
            count: count - 1,
          });
        }, 1000);
      }
      componentWillUnmount() {
        clearInterval(this.timer);
      }
    }
    //父组件
    class App extends Component {
      arr = ['1','2','3'];
      timeUpParent = (param1,param2)=>{
        alert('时间到'+'\n'+'param1是'+param1+'\n'+'param2是'+param2);
      }
      
      render() {
        return (
          <View>
            {
            this.arr.map(i=>{
            {/*传给子组件的属性的为整个箭头函数,子组件的参数为箭头函数的参数*/}
            return <CountDown key={i} timeUp={(childParam)=>{this.timeUpParent('父用于区分子组件的参数:'+i,childParam)}} />
            })
            }
          </View>
        )
      }
    }
    
    3. 任意组件之间的通信

    这些高级的东西,先暂时有个概念,知道是解决什么问题即可,先掌握以上的基础是当前之重。

    • 全局时间订阅系统(EventEmitter)
    • 单向数据流框架(Flux系)
      flux、reflux、alt、redux
    • 双向数据流框架
      mobx

    相关文章

      网友评论

        本文标题:RN(四)--组件间通信

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