Bootstrap

React进阶(八):state 属性讲解

一、前言

在《》博文中,主要讲解了的应用场景及应用示例。本文主要梳理属性的应用场景及应用实例。

二、React 渲染过程

把组件看成是一个状态机()。通过与用户的交互,实现不同状态间的切换,然后渲染 ,让用户界面和数据保持一致。

中只需更新组件的 ,然后根据新的 重新渲染用户界面(不要操作 )。

三、实例讲解

以下实例创建一个扩展名为 的 类,在 方法中使用 来修改当前时间。

添加一个类构造函数来初始化状态 ,类组件应始终使用 调用基础构造函数

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
 
  render() {
    return (
      

Hello, world!

现在是 {this.state.date.toLocaleTimeString()}.

); } } ReactDOM.render( , document.getElementById('example') );

接下来,将设置自己的计时器并每秒更新一次。

在具有许多组件的应用程序中,在销毁时释放组件所占用的资源非常重要。

每当 Clock 组件第一次加载到 中的时候,我们都想生成定时器,这在 中被称为挂载

同样,每当 Clock 生成的这个 被移除的时候,我们也会想要清除定时器,这在 中被称为卸载

可以在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
 
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
 
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
 
  tick() {
    this.setState({
      date: new Date()
    });
  }
 
  render() {
    return (
      

Hello, world!

现在是 {this.state.date.toLocaleTimeString()}.

); } } ReactDOM.render( , document.getElementById('example') );

与 方法被称作生命周期钩子。有关生命周期钩子函数详参博文《》。

在组件输出到 后会执行 钩子,可以在这个钩子上设置一个定时器。

为定时器的 ID,可以在 钩子中卸载定时器。

代码执行顺序:

四、数据自顶向下流动

父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。

这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。

以下实例中 组件将在其属性中接收到 date 值,并且不知道它是来自 Clock 状态、还是来自 Clock 的属性、亦或手工输入:

function FormattedDate(props) {
  return 

现在是 {props.date.toLocaleTimeString()}.

; } class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return (

Hello, world!

); } } ReactDOM.render( , document.getElementById('example') );

这通常被称为自顶向下或单向数据流。 任何状态始终由某些特定组件所有,并且从该状态导出的任何数据或 只能影响树中下方的组件。

想象一个组件树作为属性的瀑布,每个组件的状态就像一个额外的水源,它连接在一个任意点,但也流下来。

为了表明所有组件都是真正隔离的,我们可以创建一个 App 组件,它渲染三个Clock:

function FormattedDate(props) {
  return 

现在是 {props.date.toLocaleTimeString()}.

; } class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return (

Hello, world!

); } } function App() { return (
); } ReactDOM.render(, document.getElementById('example'));

以上实例中每个 Clock 组件都建立了自己的定时器并且独立更新。

在 应用程序中,组件是有状态还是无状态被认为是可能随时间而变化的组件的实现细节。

我们可以在有状态组件中使用无状态组件,也可以在无状态组件中使用有状态组件。

五、拓展阅读