State和生命周期

为组件添加State和声明周期

状态与属性不同 state是完全私有的,完全受控于当前组件

为组件添加state方法

  1. 在class组件中添加构造方法,在构造方法的state属性中 初始化状态 this.state
  2. React元素展示的使用state属性的date值
  3. class组件中有提供声明周期方法
export default class Clock extends React.Component {
    constructor(props) {
        //需要将props属性来调用基础构造属性
        super(props)
        this.state = {
            date : new Date()
        }
    }

    tick() {
        this.setState({
            date: new Date()
        })
    }

    componentDidMount() {
        //this.timerID 用来存储一些我们需要的值
        this.timerID = setInterval(() => {
            this.tick()
        }, 1000);
    }

    componentWillUnmount() {
        clearInterval(this.timerID)
    }

    render() {
        return(
            <h1>
                Hello, 现在是时间 {this.state.date.toLocaleTimeString()}
            </h1>
        )
    }
}

this.props属性是React中内置属性 this.state是具有特殊含义的属性,这两个属性与展示有关,其他属性我们可以自行设置存储需要的值

State

更新状态必须使用setState({ key: value })方法,而不能简单的直接赋值修改state对象,因为直接修改this.state对象 虽然修改组件的内部状态,但是并没有驱动组件进行渲染,并不会反应state的的变化,而调用setState方法,首先改变state值,然后驱动组件进行渲染,才能看到更新变化

this.setState({comment: 'Hello'});

状态更新机制:

React 为了提高性能,会将多个状态更新进行合并更新,因此你不能依靠确定现在的state或者props值就是你上次更新的stateprops值,
如果想要依靠上次的状态或者属性进行更新,需要使用特殊的方法

this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});

组件的数据传递应该是自上向下传递,我们可以将状态作为属性传递给其组件,组件之间也只应该使用属性进行传递(状态是内部拥有的不能传递)

Props与state

  • props用于定义外部接口,state用于记录内部状态
  • props的赋值是在外部使用组件时,而state存在的目的就是让组件改变的

组件不应该修改传入的props值

生命周期

React的声明周期 经历以下三个过程:

  1. 装载过程: 组件第一次在DOM树中渲染的过程
  2. 更新过程: 组件被重新渲染的过程
  3. 卸载过程: 组件从DOM中删除的过程

装载过程

依次调用以下函数:

  • constractor
  • getInitialState
  • getDefaultProps
  • componetWillMount
  • reder
  • componentDidMount

constractor 为构造函数,通常用来

  1. 初始化state
  2. 绑定成员函数

getInitialState、getDefaultProps 是ES6之前使用React.creatClss方法定义组件才会用到,我们现在使用ES6的class在构造函数中初始化state,
ClassName.defaultProps设置默认props

reder 函数是定义组件中最重要的方法,其他方法React.Component都有默认实现,可以不用重写,这个方法必须实现,用来告诉react这个组件要渲染的DOM元素,我们不应该在这个方法中改变state;当然,如果组件想要什么都不渲染 我们可以返回null或者false

componetWillMount、componentDidMount这两个函数发生在render函数的前后
我们通常不调用componetWillMount函数,因为此时并没有任何的渲染结果,即使调用setState方法也不会引发任何的重绘,而在这个方法中的实现通常可以放到constractor()方法中
componentDidMount在render函数调用完成后调用,但是并不会立即调用,而是在其它组件的render函数也完成后,将返回结果进行综合后,才能知道如何装载,完成装载,然后调用各个组件的componentDidMount函数。我们通常在此函数中进行ajax请求,然后填充组件内容

更新过程

依次调用一下函数:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

componentWillReceiveProps(nextProps)
当父组件的render函数被调用时,组件内的子组件或者组件的props改变或者都会经历更新过程,然后触发该函数。注意,当组件内的state改变时并不会触发该方法,因为该方法就是为了让我们根据新的props值来决定是否要更新state值,因为不是只有props改变时才调用该方法,我们需要比较该方法的nextProps与this.props比较,只有发生变化时才调用this.setState

当组件内调用this.forceUpdate()会强行引发一次重绘

当父组件更新时,顺序是父组件先更新,完成后更新子组件

shouldComponentUpdate(nextProps, nextState)返回一个boolean值,来决定此次渲染是否需要继续,如果返回false,会立即停止更新过程,不进行后续更新.我们可以将nextPropsnextState与当前的this.propsthis.state进行对比,来决定是否需要继续此次更新.注意,我们调用this.setState引发更新,并不会立即更新state的值,在执行此函数时,仍是更新之前的值,因此不会影响我们进行判断

componentWillUpdate、componentDidUpdate
如果shouldComponentUpdate函数返回true 就会调用这两个函数,分别在render函数前后调用,与装载过程的Did函数不同,更新的Did函数不仅在浏览器端,在服务端也会执行,但是在服务器端的react代码,是不应该执行更新过程的。类似componentDidMount函数,可以再componentDidUpdate函数中执行第三方UI库的代码来更新UI,比如执行jquery代码

卸载过程

componentWillUnmount卸载过程只会执行这一个函数,当组件将要从DOM树上移除时,适合做一些清理性的工作