封装真正可复用的 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);

显然实现时钟效果需要设置一个计时器,并且需要每秒更新 UI。理想情况下,我们希望只编写一次代码,便可以让 Clock 组件自我更新:
将函数组件转换成 class 组件
通过以下五步将 Clock 的函数组件转成 class 组件:
1.创建一个同名的 ES6 class,并且继承于 React.Component。
2.添加一个空的 render() 方法。
3.将函数体移动到 render() 方法之中。
4.在 render() 方法中使用 this.props 替换 props。
5.删除剩余的空函数声明。
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
将函数组件转换成class组件有什么好处?
1.每次组件更新时 render 方法都会被调用,但只要在相同的 DOM 节点中渲染 ,就仅有一个 Clock 组件的 class 实例被创建使用。
2.class组件可以使用如 state 或生命周期方法等很多其他特性。

向 class 组件中添加局部的 state
1.把 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 赋初值:
注意!!!这里的构造函数中使用了super()方法,这个方法是ES6规范新增的,子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

3.移除 元素中的 date 属性:
function tick() {
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
}
4.将计时器相关的代码添加到组件中。
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')
);
将生命周期方法添加到 Class 中
当 Clock 组件第一次被渲染到 DOM 中的时候,就为其设置一个计时器。这在 React 中被称为“挂载(mount)”。
同时,当 DOM 中 Clock 组件被删除的时候,应该清除计时器。这在 React 中被称为“卸载(unmount)”。
我们可以为 class 组件声明一些特殊的方法,当组件挂载或卸载时就会去执行这些方法:这些方法叫做“生命周期方法”。
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() { }
componentWillUnmount() { }
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}

最后,我们会实现一个叫 tick() 的方法,Clock 组件每秒都会调用它。使用 this.setState() 来时刻更新组件 state:

