我们可以从封装时钟的外观开始:
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()} />,//初始化date document.getElementById('root') ); } setInterval(tick, 1000);//注意行代码在外面自己运行,一会将会进行封装
运行:https://codepen.io/gaearon/pen/dpdoYR?editors=0010
然而,它忽略了一个关键的技术细节:Clock
组件需要设置一个计时器,并且需要每秒更新 UI。(组件本身自己调用,而不是外部运行)
理想情况下,我们希望只编写一次代码,便可以让 Clock
组件自我更新
代码如下:
ReactDOM.render( <Clock />,//这里不用传初始化 document.getElementById('root') );
我们需要在 Clock
组件中添加 “state” 来实现这个功能。
State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件。
将函数组件转换成 class 组件
通过以下五步将 Clock
的函数组件转成 class 组件:
- 创建一个同名的 ES6 class,并且继承于
React.Component
。 - 添加一个空的
render()
方法。 - 将函数体移动到
render()
方法之中。 - 在
render()
方法中使用this.props
替换props
。 - 删除剩余的空函数声明。
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.date.toLocaleTimeString()}.</h2> </div> ); } }
现在 Clock
组件被定义为 class,而不是函数。
每次组件更新时 render
方法都会被调用,但只要在相同的 DOM 节点中渲染 <Clock />
,就仅有一个 Clock
组件的 class 实例被创建使用。这就使得我们可以使用如 state 或生命周期方法等很多其他特性。
向 class 组件中添加局部的 state(封装)
我们通过以下三步将 date
从 props 移动到 state 中:
- 把
render()
方法中的this.props.date
替换成this.state.date
:
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
2.添加一个 class 构造函数,然后在该函数中为 this.state
赋初值:
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } }
Class 组件应该始终使用 props
参数来调用父类的构造函数。
3. 移除 <Clock />
元素中的 date
属性:
ReactDOM.render( <Clock />, document.getElementById('root') );
我们之后会将计时器相关的代码添加到组件中。
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
运行:https://codepen.io/gaearon/pen/KgQpJd?editors=0010
官网:https://react.docschina.org/docs/state-and-lifecycle.html