这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
首先,我们通过一个例子来引出:计数器
1. 挂载阶段
- constructor 构造器
- componentWillMount 将要挂载
- componentDidMount 挂载完毕
- render 渲染
我们在每个生命周期的钩子中都 打印一下,看他们的执行顺序。
class Count extends React.Component {
constructor(props) {
console.log("count-constructor")
super(props)
// 初始化状态
this.state = {
count: 0
}
}
// 将要挂载
componentWillMount() {
console.log("componentWillMount")
}
//挂载完毕
componentDidMount(){
console.log("componentDidMount")
}
// +1 按钮回调
add = () => {
//获取原状态
const { count } = this.state
// 更新状态
this.setState({ count: count + 1 })
}
render() {
console.log("count-render")
return (
<div>
<h1>当前求和为{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
</div>
)
}
}
执行顺序如下: 可以看到图中的警告,componentWillMount 已经被遗弃了。但是依旧可以使用。
2. 更新
更新有如下三种方式:
2.1 setState
之前的文章中,我们说setState 更新会 调用 render。但是其实还经历了 shouldComponentUpdate(否应该更新组件)、componentWillUpdate两个过程。
- shouldComponentUpdate
? 我们之前一直没有写过shouldComponentUpdate这个钩子函数函数啊?为什么也更新了呢? 这个钩子有返回值,默认的返回值是true,只有他的返回值是true,才能向下执行。当我们自己写这个钩子函数,并且返回值是false的时候。就不会向下执行了。⚠️ 必须要有返回值true/false。
shouldComponentUpdate(){
console.log("shouldComponentUpdate")
return true
}
- componentWillUpdate 组件将要更新的钩子
- componentDidUpdate 组件更新完毕的钩子
2.2 forceUpdate
强制更新,也就是不想使用setState也要更新状态。与setState的区别也就是在于:不经过 shouldComponentUpdate。
我们新增一个按钮,点击按钮出发force回调函数。回调函数中使用forceUpdate。forceUpdate和setState一样都需要this.
force =()=>{
this.forceUpdate()
}
render() {
console.log("count-render")
return (
<div>
<h1>当前求和为{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>销毁</button>
<button onClick={this.force}>强制更新</button>
</div>
)
}
点击强制更新后,我们发现如下三个钩子都执行了。
以上两种方式的完整代码
class Count extends React.Component {
constructor(props) {
console.log("count-constructor")
super(props)
// 初始化状态
this.state = {
count: 0
}
}
// 将要挂载
componentWillMount() {
console.log("componentWillMount")
}
//挂载完毕
componentDidMount() {
console.log("componentDidMount")
}
// +1 按钮回调
add = () => {
//获取原状态
const { count } = this.state
// 更新状态
this.setState({ count: count + 1 })
}
// 卸载组件的回调
death = () => {
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
// 组件将要卸载调用
componentWillUnmount() {
console.log("componentWillUnmount")
}
// 控制组件更新的“阀门”
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return true
}
// 组件将要更新的钩子
componentWillUpdate() {
console.log("componentWillUpdate")
}
// 组件更新完毕的钩子
componentDidUpdate() {
console.log("componentDidUpdate")
}
force = () => {
this.forceUpdate()
}
render() {
console.log("count-render")
return (
<div>
<h1>当前求和为{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>销毁</button>
<button onClick={this.force}>强制更新</button>
</div>
)
}
}
2.3 父组件render
首先我们新写两个组件,让他们两个构成父子关系。
class A extends React.Component {
render() {
return (
<div>
A
<B />
</div>
)
}
}
class B extends React.Component {
render() {
return (
<div>B</div>
)
}
}
ReactDOM.render(<A />, document.getElementById('root'))
在A组件(父组件)的state中定义一个变量carName,并且在A组件中添加按钮和改变carName的回调函数。最重要的是,我不想在A组件中展示这个车名,我要放到B组件中展示。
class A extends React.Component {
state ={carName:"BM"}
changeCar = ()=>{
this.setState({carName:"AD"})
}
render() {
return (
<div>
我是A组件
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
)
}
}
B组件(子组件),就通过props接收父组件A,传来的值
class B extends React.Component {
render() {
return (
<div>我是B组件,接收到的是{this.props.carName}</div>
)
}
}
那么就引出了钩子 componentWillReceiveProps (组件将要接收props)
class B extends React.Component {
componentWillReceiveProps(){
console.log("componentWillReceiveProps")
}
render() {
return (
<div>我是B组件,接收到的是{this.props.carName}</div>
)
}
}
第二次接收props
我们刚一进页面,父组件已经向子组件传递了 props。但是这个钩子并没有执行。当我们点击按钮进行更新时,才执行了此钩子。
3. 销毁
点击按钮销毁组件,我们在 componentWillUnmount 钩子函数中进行打印。当点击按钮,执行此打印。
death =()=>{
ReactDOM.unmountComponentAtNode(document.getElementById('root'))
}
// 组件将要卸载的钩子
componentWillUnmount(){
console.log("componentWillUnmount")
}
render() {
console.log("count-render")
return (
<div>
<h1>当前求和为{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>销毁</button>
</div>
)
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!