组件的生命周期

详细的生命周期文档

博客

其他Tips

  • render中只做与渲染有关的操作,只读取、不修改任何数据(临时变量除外)
    • 因为界面的更改是经常的,所以render是经常触发的
    • 所以如果你有修改数据等操作,就会多次触发,使结果难以预料
    • 比如你执行setState,那么setState又触发render,就会导致死循环
  • 随组件加载只执行一次的操作,放在WillMount或者DidMount中
    • 比如远程取首页数据(fetch),比如弹出提示框
  • 记得在WillUnmount中销毁定时器和一些订阅事件
  • props发生变化,使用WillReceiveProps来处理(比如将变动同步给state)

组件之间的相互通信

存在的情况

  1. 父组件向子组件进行调用,传递
  2. 子组件之间的相互通信
  3. 子组件向父组件进行通信
  4. 全局跨任意组件间通信

父组件向子组件进行调用,传递/子组件之间的相互通信

  1. 父组件将自身的state作为子组件的属性props进行传递,父组件调用setState,于是子组件的props相应变化
  2. 通过使用进行调用子组件的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // 推荐写法
    class App extends Component {
    render() {
    return (
    <CountDown ref={
    instance => this.countDown = instance
    } />
    )
    }
    componentDidMount() {
    this.countDown.add(10086);
    }
    }
    // 不推荐写法
    class App extends Component {
    render() {
    return (
    <CountDown ref={
    instance => this.countDown = instance
    } />
    )
    }
    componentDidMount() {
    this.countDown.add(10086);
    }
    }

子组件向父组件进行通信

  1. 父组件将函数作为props传递给子组件,子组件在需要的时候进行调用,可以将数据作为函数参数进行回传
    • 类似于iOS中的block
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      class CountDown extends Component {
      state = {
      count: this.props.time,
      };
      render() {
      const { count } = this.state;
      return (
      <Text>{count}</Text>
      )
      }
      add = (time) => {
      this.setState({
      count: this.state.count + time
      })
      }
      componentDidMount() {
      this.timer = setInterval(() => {
      const { count } = this.state;
      if (count === 0) {
      this.props.timeout && this.props.timeout( 1 );
      return clearInterval(this.timer);
      }
      this.setState({
      count: count - 1,
      });
      }, 1000);
      }
      componentWillUnmount() {
      clearInterval(this.timer);
      }
      }
      class App extends Component {
      addTime = () => {
      this.countDown.add(5)
      }
      timeOut = (params) => {
      alert('爸爸知道了' + params)
      }
      render() {
      return (
      <View>
      <TouchableOpacity onPress={this.addTime}>
      延长十秒
      </TouchableOpacity>
      <CountDown ref={ countdown => this.countDown = countdown} time = '3' timeout={this.timeOut} />
      </View>
      )
      }
      }
      AppRegistry.registerComponent('App', () => App)

Note

  1. 跟iOS一样如果一个传入的函数(iOS为Block),加上了括号,那么即会变成函数调用
  2. 根据1,在动态列表中,想传入对应参数就比较困难,所以有以下方法
1
2
3
4
5
6
7
8
9
// 如何传入参数以区分不同的点击呢?
arr.map(d => <Text key={d.id} onPress={this.handlePress}>{d.text}</Text>)
// 错误使用,这么做会直接执行
arr.map(d => <Text key={d.id} onPress={this.handlePress(d.id)}>{d.text}</Text>)
// 正确使用
arr.map(d => <Text key={d.id} onPress={() => this.handlePress(d.id)}>{d.text}</Text>)
arr.map(d => <Text key={d.id} onPress={this.handlePress.bind(this, d.id)}>{d.text}</Text>)
正确!箭头函数或bind都会生成新函数。传入参数以闭包的形式“封存”,留待调用。

这里有个坑,父类传到子类,因为函数被bind或者箭头函数重新进行了包装,所以在传参的时候,用在新的参数里面重新添加参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 实例代码
class CountDown extends Component {
state = {
count: this.props.time,
};
render() {
const { count } = this.state;
return (
<Text>{count}</Text>
)
}
add = (time) => {
this.setState({
count: this.state.count + time
})
}
componentDidMount() {
this.timer = setInterval(() => {
const { count } = this.state;
if (count === 0) {
this.props.timeout && this.props.timeout("123");
return clearInterval(this.timer);
}
this.setState({
count: count - 1,
});
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
}
class App extends Component {
addTime = () => {
this.countDown.add(5)
}
timeOut = (params1,params2) => {
alert('爸爸知道了' + params1 + params2)
}
state = {
arr: [5,4,3]
}
render() {
return (
<View>
{
this.state.arr.map (i => {
return <CountDown key={i} time={i} timeout={(child) => this.timeOut(i,child)}/>
})
}
</View>
)
}
}
AppRegistry.registerComponent('App', () => App)

双向通信

  1. 全局时间订阅系统(EventEmitter)
  2. (Flux系)单向数据流框架
    • flux
    • reflux
    • alt
    • redux
  3. 双向数据流狂阶
    • mobx