老生命周期存在的一些问题
1.componentWillMount:在ssr中 这个方法将会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致
内存泄漏 ,变得不够安全高效,逐步废弃。
2.componentWillReceiveProps:外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求。
3.componetWillupdate:更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长,会导致状态不可信。
1.初始化阶段
(1)componentWillMount:将要挂载
客户端一辈子只执行一次,服务端渲染会执行多次,render之前最后一次修改状态的机会,(类似于:vue 中的 beforeMount)。如果
在这里要发Ajax、setInterval会有隐患,在服务端渲染的时候,这个生命周期会重复执行,会导致Ajax发送多次请求、定时器会关闭不了。
(2)render:正在渲染
只能访问this.props 和 this.state,不允许修改状态和DOM输出。
(3)componentDidMount: 已经挂载完了
一辈子只执行一次,在render成功渲染完真实的DOM后触发,可以修改DOM(类似于:vue 中的 Mounted)
import React, { Component } from 'react'
export default class App extends Component {
state = {
list:[]
}
/*
不建议用这个生命周期,不安全,如果非要用的话,
加上一个UNSAFE_ --> UNSAFE_componentWillMount(){},
17版本要加UNSAFE_
*/
componentWillMount(){
/*
Ajax和setInterval一般不写在这里,一般写在componentDidMount里,因为有个隐患,
将来在服务端渲染的时候,这个生命周期会重复执行,Ajax和setInterval多次执行,
会导致Ajax发送多次请求、定时器会关闭不了
*/
}
componentDidMount() {
// Ajax、常规工作、绑定事件、启动定时器
// React没有新的Ajax请求方式 --> fetch、axios
// 如果要做假数据,把json文件放在public静态资源文件夹下
fetch("/test.json").then(res=>res.json()).then(res=>{
console.log(res)
this.setState({
list:res.coming
})
})
}
render() { // 每次重新渲染页面的时候,都会走一遍render
return (
<div>
{
this.state.list.map(item=>
<li key={item.id}>
<img src={item.img.replace('w.h','128.180')}/>
{item.nm}
</li>
)
}
</div>
)
}
}
2.运行中阶段
1.componentWillReceiveProps(nextProps,nextState){}:
父组件修改属性时触发(要建立在父子关系下才会用到这个生命周期,写在子组件身上)父子通信的时候,因为componentDidMount
只执行一遍,componentWillReceiveProps会走多次,所以获取不到新的Ajax数据,要在componentWillReceiveProps中获取Ajax
2.shouldComponentUpdate:
组件是否更新了,返回false会阻止render调用
3.componentWillUpdate:
不能修改属性和状态
4.render:
只能访问 this.props 和 this.state,不允许修改状态和DOM输出
5.componentDidUpdate:
可以修改DOM
没有父子关系的情况:
import React, { Component } from 'react'
export default class App extends Component {
state = {
myname:"kerwin"
}
componentWillUpdate(){ // 3.将要更新
}
componentDidUpdate(){ // 5.已经更新完了
}
componentWillReceiveProps(){
// 要在父子通信的情况下才使用,写在子组件身上,因为App是根组件,所以App没有父组件,
}
// 7.优化性能:判断myname这个状态是否改变了,改变了就走更新,没改变就不走更新
// shouldComponentUpdate -- 性能调优函数
shouldComponentUpdate(nextProps, nextState) { // (代码提示:scu)
// 8.状态myname改变了
// (对比:nextProps是老的,在父子通信下才会用 nextState是新的 )
// (对比:this.state.myname是老的 nextState.myname是新的 )
if(this.state.myname !== nextState.myname){
return true // true就更新
}
return false // 状态没改变,false就不更新
}
// 4.正在更新
render() {
// 1.先渲染一遍页面
return (
<div>
{this.state.myname}
{/*
2.调用setState方法的时候,会开启更新
*/}
<button onClick= {()=>{
this.setState({
myname:"xiaoming"
})
}}>click</button>
{/* 6.setState之后 --> 会进行更新 --> 虚拟DOM创建 --> Diif算法比较,
把对比的补丁更新到页面中,这个过程是异步的很慢,每次调用setState都会重新走一遍这个过程,
这样会导致浏览器会很累,组件性能不好
*/}
</div>
)
}
}
有父子关系的情况:
import React, { Component } from 'react'
class Child extends Component{
componentDidMount() { // 只会走一次
{/* this.props.myname是老的属性 */}
console.log('Ajax请求数据', this.props.myname)
}
{/* nextProps -- 根据新的数据获取新的属性 */}
componentWillReceiveProps(nextProps) { // 会走多次
{/* this.props.myname是老的属性 */}
{/* nextProps.myname是新的属性 */}
console.log('Ajax请求数据', nextProps.myname)
}
{/*
componentWillReceiveProps这个生命周期也有问题,加上UNSAFE_
--> UNSAFE_componentWillReceiveProps
*/}
render(){
return <div>
{/* 这样子组件就只需要做页面渲染 */}
child组件-{this.props.myname}
</div>
}
}
export default class App extends Component {
state= {
myname:"4567"
}
render() {
return (
<div>
{this.state.myname}
<button onClick={()=>{
this.setState({
myname:"4321"
})
}}>click</button>
<Child myname={this.state.myname}></Child>
</div>
)
}
}
3.销毁阶段
componentWillUnmount:
在删除组件之前进行清理操作,比如:计时器和事件监听器
import React, { Component } from 'react'
class Navbar extends Component{
render(){
return <div style={{background:"red"}}>
navbar-<button onClick={this.handleClick}>click</button>
</div>
}
handleClick = ()=>{
console.log(this.props.onKerwinEvent)
this.props.onKerwinEvent()
}
}
class Sidebar extends Component{
render(){
return <div style={{background:"yellow"}}>
Sidebar
<ul>
<li>11111</li>
<li>222222</li>
<li>33333</li>
</ul>
</div>
}
componentWillUnmount(){
// 卸载生命周期 --> 清除定时器、scroll为空
}
}
export default class App extends Component {
state = {
isShow:true
}
render() {
return (
<div>
App
<Navbar onKerwinEvent={()=>{
console.log("App 组件的回调函数")
this.setState({
isShow:!this.state.isShow
})
}}/>
{/* <button onClick={()=>{
this.setState({
isShow:!this.state.isShow
})
}}>click</button> */}
{
this.state.isShow?
<Sidebar/>
:null
}
</div>
)
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4571.html