一、状态和生命周期
状态state
, 生命周期 liftcircle
.
之前说过,一旦元素被渲染了之后就不可改变了,但我们可以通过重新渲染的方法使页面得以刷新,同样我们提到过最常用的方法是编写一个可复用的具有状态的组件,这里的状态,就是我们将要说的 state
我们对上述提过的计时器tick
中的计时功能封装成一个函数式组件如下:
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
)
}
然后把他当做一个元素放入 tick
中进行渲染
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
)
}
setInterval(tick, 1000);
在这个例子中,我们将计时功能代码封装成了一个独立的可复用的组件,并通过属性date的方式将参数传入,但还不能到达我们想要的结果,那就是不能再组件内部修改参数值,组件中显示的数据依旧受控于父组件中date
属性传递过来的值,那如果我们把这个date
属性也添加到Clock
内部呢?来看下
ReactDOM.render(
<Clock />,
document.getElementById('root')
)
这时父组件中只保留了对计时组件Clock
的一个单纯的引用。剩下的事情全部依托以组件Clock
自己去实现。要怎么实现这个需求?这里React提出了另一个数据对象,即state
,它用来保存组件内部的数据,与props
类似,不同的是state
是组件私有的,并且由组件本身完全控制。它能实现数据在组件内部的修改和更新。怎么使用这个state
?继续往下讲之前我们先拓展一个知识
我们知道组件有两种定义方式,即函数式组件和类组件,虽然函数式组件更加简洁更加接近原生 javascript
,但类组件却拥有一些额外的属性,这个类组件专有特性,就是状态和生命周期钩子,到这里也能清楚知道状态的关键作用,然而函数式组件没有这两个特性,因此,在需要使用到状态state
情况下,我们需要将函数式组件转换成类组件
函数式组件转化成类组件
尝试把一个函数式组件转化成类组件,官网给出了以下步骤,以Clock
组件为例
- 创建一个继承自
React.Component
类的ES6 class
同名类 - 添加一个名为
render()
的空方法 - 把原函数中的所有内容移至
render()
中 - 在
render()
方法中使用this.props
替代props
- 删除保留的空函数声明
class Clock extents React.Component {
render() {
return (
<div>
<h1>Hello, world</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
)
}
}
到此,Clock
组件已经成功被我们修改成了一个类组件,我们便可以在其中添加本地状态state
和生命周期钩子
class Clock extends React.Component {
// 用类构造函数constructor初始化 this.state
constructor(props) {
// 使用super()将props传递给基础构造函数
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
)
}
}
这样,我们的类组件Clock
就拥有了自己的属性 this.state.date
,也就不需要引用组件向其传递值了,因此,我么可以把组件引用中的date
属性删掉,最终,我们将其渲染到DOM上,只使用组件引用,其他都交给组件Clock
自己去实现
ReactDOM.render(
<Clock />,
document.getElementById('root')
)
到这里就结束了?细心的你会发现,组件Clock
只是实现了当前时间的显示,而我们要改装的功能是一个计时器,计时功能去哪里了?没实现啊?我们需要在组件Clock
中找到一个合适的时机去实现这个功能,为此,React团队引入了 声明周期方法,也叫生命周期钩子
在类组件中添加生命周期方法
在一个具有许多组件的应用程序中,在组件被销毁时释放所占用的资源是非常重要的。就像浏览器的垃圾回收机制,近期内不需要再用的资源,应该及时清除。
当 Clock
第一次渲染到DOM时,我们要设置一个定时器 。 这在 React 中称为 “挂载(mounting)” 。它有一个生命钩子componentDidMount()
当 Clock
产生的 DOM 被销毁时,我们也想清除该计时器。 这在 Rea