React Native 基础知识2

React Native

Posted by ddxg on January 14, 2018

React Native 基础知识2

1. 父组件向子组件通信、子组件之间通信

  • 父组件以自身的state作为子组件的props;父组件调用setState,于是子组件的props相应变化
  • 通过ref调用子组件的方法

有个例子:

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
} from 'react-native'

class CountDown extends Component {
  /* 设置初始时间为20s */
  state = {
    count : 20
  };
  /* 提供一个成员方法addTime来供外部组件调用 */
  addTime = (time) => {
    this.setState({
      count: this.state.count + time
    });
  };
  render() {
    return (
      <View>
        <Text style={styles.welcome}>
          倒计时:{this.state.count}
        </Text>
      </View>
    )
  }
  /* 生命周期,render后会调用componentDidMount() */
  componentDidMount() {
    /* 来一个定时器 */
    
    this.timer = setInterval(() => {
      const {count} = this.state;
      if (count == 0) {
        clearInterval(this.timer);
      } else {
        this.setState({
          count: count - 1
        });
      }
    }, 1000);
  }
  /* 生命周期中组件卸载后调用的方法,清空定时器 */
  componentWillUnmount() {
    clearInterval(this.timer);
  }
}

class App extends Component {
  addTime = () => {
  /* 调用子组件的addTime方法 */
    this.countDown.addTime(10);
  };
  render() {
    return (
      <View style={styles.container}>
        {/* 通过ref引用获取CountDown实例,并且赋值给this.countDown */}
        <CountDown ref={countDown => this.countDown = countDown}/>
        {/* 添加点击事件 */}
        <TouchableOpacity onPress={this.addTime}>
          <Text>延长10秒</Text>
        </TouchableOpacity>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
})

AppRegistry.registerComponent('App', () => App)

有一个倒计时的组件CountDown,初始秒数为20,秒数每隔一秒减一。点击父组件中的TouchableOpacity组件,就可以让CountDown的倒计时秒数增加10。就是父组件向子组件通信,让子组件改变状态。

这里写图片描述

最重要的是这个ref的赋值

<CountDown ref={countDown => this.countDown = countDown}/>

将CountDown组件的实例赋值给this.countDown,这样就可以通过this.countDown.addTime(10) 来调用CountDown组件的addTime() 成员方法。

2. 子组件向父组件通信

父组件将函数作为props传递给子组件,子组件在需要时调用,将数据作为函数参数传回。此谓之“回调”(callback)

当时间没有的时候,子组件会通知父组件(调用父组件穿过来的方法)。

import React, { Component } from 'react'
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
} from 'react-native'

class CountDown extends Component {
  /* 设置初始时间为20s */
  state = {
    count : 20
  };
  /* 提供一个成员方法addTime来供外部组件调用 */
  addTime = (time) => {
    this.setState({
      count: this.state.count + time
    });
  };
  /* 调用父组件通过props传来的方法 */
  noTime = () => {
    this.props.noTime && this.props.noTime('123');
  }
  render() {
    return (
      <View>
        <Text style={styles.welcome}>
          倒计时:{this.state.count}
        </Text>
      </View>
    )
  }
  /* 生命周期,render后会调用componentDidMount() */
  componentDidMount() {
    /* 来一个定时器 */
    this.timer = setInterval(() => {
      const {count} = this.state;
      if (count == 0) {
      /* 当时间为0时,调用noTime方法告诉父组件没有时间了 */
        this.noTime();
        clearInterval(this.timer);
      } else {
        this.setState({
          count: count - 1
        });
      }
    }, 1000);
  }
  /* 生命周期中组件卸载后调用的方法,清空定时器 */
  componentWillUnmount() {
    clearInterval(this.timer);
  }
}

class App extends Component {
  arr = ['111', '222', '333'];
  noTimeParent = (parentData, childData) => {
    alert("父组件传过去的数据:" + parentData + "\n子组件传回的数据:" + childData);
  };
  render() {
    return (
      <View style={styles.container}>
        {/* 像子组件传递一个父组件的函数,为了传递参数需要在父组件函数外面多包一层函数 */}
        {/* 第一个参数是用于标识哪一个组件的,第二个参数是为子组件回传参数做准备 */}
        {this.arr.map((arrName) => <CountDown key={arrName} noTime={(child) => this.noTimeParent(arrName, child)}/>)}
        
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
})

AppRegistry.registerComponent('App', () => App)

比较复杂的地方:

{
this.arr.map((arrName) => 
  <CountDown key={arrName} 
    noTime={
      (child) => this.noTimeParent(arrName, child)
    }
  />)
}

将父组件的noTimeParent 成员方法通过props传给子组件,为了传递有标识度的参数需要在父组件函数外面多包一层函数,这里传了数组arr中的内容作为参数。

  noTime = () => {
    this.props.noTime && this.props.noTime('123');
  }

在子组件的noTime方法中,this.props.noTime('123') 这里调用的方法是(child) => this.noTimeParent(arrName, child) 这个方法,'123' 对应的就是这个child。 所以在父组件的noTimeParent方法中,parentData 就是传给子组件的数据,childData 就是子组件回传的数据。

noTimeParent = (parentData, childData) => {
    alert("父组件传过去的数据:" + parentData + "\n子组件传回的数据:" + childData);
  };

这里写图片描述