react学习教程

[React] State & 生命周期(4)

2018-08-07  本文已影响0人  水流云间

state(状态)与props(属性)的差异

state(状态)是私有的,完全受控于当前组件,用于改变组件内容状态的值;
props(属性)用于组件通讯进行传值,是由父级传向子级的,在React中规定不可在子级修改它的值。

如果要实现一个Clock的组件,可以选择通过在父组件里setInterval,改变props中date的值,来实现Clock里展示的改变。

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

但这样耦合度太高,如果能写一次Clock,它自身就能更新,这才是最好的实现方式。

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

定义和设置state

  1. 定义state,需要在继承自Component的组件的类中,且构造函数是唯一能够初始化 this.state 的地方。
  2. 调用时使用this.state.xxx
  3. 使用setState()设置state。
class Clock extends React.Component {
    // 构造函数
    // 父级的props可通过构造函数传入
    constructor(props) {
        super(props);
        this.state = {
            date: new Date()
        };
    }

    // 渲染
    render() {
        return (
            <div>
                <h1>让人期待时钟-{ this.props.index }</h1>
                <p>现在的时间是:{ this.state.date.toLocaleTimeString() }</p>
            </div>
        );
    }
...
}

正确地使用状态(setState()三大事)

1. 不要直接更新状态,那样并不会重新渲染组件
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
2. 状态更新可能是异步的

React 可以将多个setState()调用合并成一个调用来提高性能。
因为this.propsthis.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});
// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
3. 状态更新合并

当你的状态有多个属性,并且调用setState()独立地更新它们时,React 将它们的值浅合并到当前状态。

// 两次设置不同的字段值
this.setState({
    posts: 12
});
this.setState({
    comments: 3
});


// 等同于
this.setState({
    posts: 12,
    comments: 3
});

生命周期钩子(先暂时列常用的)

  1. componentDidMount
    在第一次渲染后调用,只在客户端。
    之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
    一般用来挂载一些事件,定时器等。

  2. componentWillUnmount
    在组件从 DOM 中移除的时候立刻被调用。
    卸载不需要的事件,定时器等。

用所学知识,写一个完整的Clock组件

  1. 新建Clock.js文件。
import React from 'react';

class Countdown extends React.Component {
    // 构造函数
        // 父级的props可通过构造函数传入
    constructor(props) {
        super(props);
        this.state = {
            date: new Date()
        };
    }

    // 渲染
    render() {
        return (
            <div>
                <h1>让人期待时钟-{ this.props.index }</h1>
                <p>现在的时间是:{ this.state.date.toLocaleTimeString() }</p>
            </div>
        );
    }

    // 倒计时动作
    tick() {
        this.setState({
            date: new Date()
        });
        // 参数为:先前的状态,已被应用的props
        this.setState((prevState, props) => {
            console.log(prevState, props);
        });
    }

    // 组件挂载后执行的生命周期钩子
    componentDidMount() {
        this.timeId = setInterval(() => {
            this.tick();
        }, 1000);
    }

    // 组件将要挂载时执行的生命周期钩子
    componentWillUnmount() {
        clearInterval(this.timeId);
    }
}

export default Clock;
  1. 在App.js里引用
import React from 'react';
import ReactDOM from 'react-dom';
import Clock from './Clock';

const element = (
    <div>
        <Clock index="0" />
        <Clock index="1" />
        <Clock date={new Date()} index="2" />
    </div>
);

ReactDOM.render(element, document.getElementById('root'));
  1. 效果如图


上一篇下一篇

猜你喜欢

热点阅读