当前位置: 首页> 汽车> 时评 > 软件开发过程的五个阶段_免费动画模板素材网站_中国疫情最新消息_外贸网站模板

软件开发过程的五个阶段_免费动画模板素材网站_中国疫情最新消息_外贸网站模板

时间:2025/7/11 10:31:54来源:https://blog.csdn.net/Au_ust/article/details/146302713 浏览次数: 1次
软件开发过程的五个阶段_免费动画模板素材网站_中国疫情最新消息_外贸网站模板

函数式组件只有属性,没有状态,更没有生命周期的概念,但是函数式组件在React16.8引入hooks以后,可以在函数式组件里使用state和生命周期等特性,拥有类似于类组件的能力,同时保持简洁和易用性。

在生命周期的某个阶段会触发的东西

写不写本身不会影响组件的执行,但是写的话会在生命周期的某个阶段触发

整个生命中周期分为三个阶段:初始化阶段、运行阶段、销毁阶段

初始化阶段

执行顺序:WillMount=>render=>DidMount
import React, { Component } from 'react';class App extends Component {state={myname:'荷叶饭'}componentWillMount() {console.log('WillMount', this.state.myname, document.getElementById('myname'))//WillUnmount,将要挂载到组件中,只会执行一次,上树(上dom树)前的最后一次修改状态的机会,但是拿不到dom//简单说就说初始化数据的作用this.setState({myname:'励志轩'})
}componentDidMount() {console.log('DidMount',document.getElementById('myname'))//DidMount,已经挂载到组件中,只会执行一次//一般放置数据请求,axios,ajax,订阅函数的调用,setInterval//基于创建完的dom进行初始化,BetterScroll就说基于创建完的dom来让长列表滚动}render() {console.log('render')// 写完以后会自动执行return (//render里不能直接修改状态,所以WillMount是上树前的最后一次修改状态的机会<div><span id='myname'>{ this.state.myname}</span></div>);}
}export default App;
React中的生命周期函数,也叫做钩子函数,钩子函数起到的作用是被咬钩的时候我知道了
这里报警告是因为WillMount 生命周期方法,该方法在 React 16.3 之后已被标记为 不安全的(unsafe),所以上面写的东西只适用于React16.2以前
我真是服了缝缝补补的前端

React版本的重要节点:16.2之前都是老版本的生命周期函数,使用的时候可以自己将其重命名为UNSAFE_componentWillMount,相当于自己提醒自己

警告消失了:

因为在16.2以后优化了diff(新的对比旧的)算法,提出了Fiber(纤维,新协调算法,支持异步渲染、渲染优先级调度),WillMount就属于进行diff算法的部分,为第一优先级,以前来说要等它执行完毕,但是根据新的机制会打断第一优先级,所以在后期的使用就有了安全隐患
函数组件在 16.8之前也是没有生命周期的
用我们刚学的componentDidMount来做数据请求
WillMount应用实例
import React, { Component } from 'react';
import BetterScroll from 'better-scroll'
class App extends Component {state = {list:['111','222','333','444','555','666','777','888','999','121']}UNSAFE_componentWillMount() {//获取不了dom节点}componentDidMount() {//可以获取dom节点new BetterScroll('#wrapper')}render() {return (<div><div id='wrapper' style={{background:'yellow',height:'200px',overflow:'hidden'}}><ul>{this.state.list.map(item => <li key={item}>{item}</li>)}</ul></div></div>);}
}export default App;

运行中阶段

看看他们render、componentDidUpdate、componentWillUpdate三个的执行顺序:
import React, { Component } from 'react';class App extends Component {state = {myname:'kerwin'
}render() {console.log('render')return (<div><button onClick={() => {this.setState({myname:'tiechui'})}}>click</button><span id='myname'> {this.state.myname}</span></div>)}UNSAFE_componentWillUpdate() {console.log('componentWillUpdate',document.getElementById('myname').innerHTML)}componentDidUpdate() {console.log('componentDidUpdate',document.getElementById('myname').innerHTML)}}export default App;
render=>点击按钮=>componentWillUpdate=>render=>componentDidUpdate
先渲染=>点击按钮以后=>准备更新=>正在更新=>更新完成
每次更新完dom的时候new一个BetterScroll,加上if判断可以防止new多次的BetterScroll
import React, { Component } from 'react';
import BetterScroll from 'better-scroll'import axios from 'axios'
class App extends Component {state = {myname: 'kerwin',list:[]
}componentDidMount() {axios.get('/test.json').then(res => {console.log(res.data.data.films)this.setState({list:res.data.data.films},)})
}render() {console.log('render')return (<div><button onClick={() => {this.setState({myname:'tiechui'})}}>click</button><span id='myname'> {this.state.myname}</span><div id='wrapper' style={{height:'100px',overflow:'hidden',background:'pink'}}><ul>{this.state.list.map(item => <li key={item.filmId}>{item.name}</li>)}</ul></div></div>)}UNSAFE_componentWillUpdate() {console.log('componentWillUpdate',document.getElementById('myname').innerHTML)}componentDidUpdate(prevProps,prevState) {console.log('componentDidUpdate', document.getElementById('myname').innerHTML)if (prevState.list.length === 0) {new BetterScroll('#wrapper')}}}export default App;

但是如果只有这个三个普通的生命周期函数,那么只要点击按钮,即使state并没有变化,也会调用render函数

SCU

这时候就需要shouldComponentUpdate,这个函数简称SCU,性能优化函数(同理CDM是componentDidMount,),来判断组件是否应该更新:

shouldComponentUpdate(nextProps,nextState) {//return true//应该更新//return false//阻止更新//做条件判断:if (this.state.myname!==nextState.myname) {return true}return false
}

如果要对比的内容是对象,可以转化为json字符串对比:

SCU优化性能的案例:
import React, { Component } from 'react';class Box extends Component{
//优化思路:只拿改变的div和前一个做对比就好了shouldComponentUpdate(nextProps) {if (this.props.current===this.props.index||nextProps.current===nextProps.index) {return true}return false
}render() {return <divstyle={{ width: '100px', height: '100px', border: this.props.current === this.props.index ? '5px solid red' : '5px solid grey', margin: '10px', float: 'left' }}></div>}
}class App extends Component {state = {list: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10',],current:0
}render() {return (<div><input type='number' onChange={(e) => {console.log(e.target.value)this.setState({current:Number(e.target.value)})}} /><div style={{overflow:'hidden'}  }>{this.state.list.map((item, index) => <Box key={item} current={this.state.current} index={index} />)}</div></div>);}
}export default App;

最先获取父组件传来的属性,相当于子组件里的初始化

import React, { Component } from 'react';class Child extends Component{state = {title:''}render() {return (<div>child-{this.state.title}</div>)}UNSAFE_componentWillReceiveProps(nextProps) {console.log(' UNSAFE_componentWillReceiveProps',this.props.text)//第一次点击按钮拿到的是老属性,11111111console.log(' UNSAFE_componentWillReceiveProps', nextProps)//拿到的是新属性,22222222//该生命周期最先获得父组件传来的属性,可以利用属性进行ajax或者逻辑处理//把拿到的属性转化为自己孩子的状态this.setState({title:nextProps.text+'荷叶饭'})}
}class App extends Component {state = {text:'11111111'
}render() {return (<div>{this.state.text}<button onClick={() => {this.setState({text:'22222222'})}}>click</button><Child text={this.state.text} /></div>);}
}export default App;

请求到的是老的数据,需要加入形参nextProps

componentWillReceiveProps

外部组件多次频繁更新传入多次不同的 props ,会导致不必要的异步请求
/** @作者: kerwin* @公众号: 大前端私房菜*/
import React, { Component } from 'react'
import axios from 'axios'
export default class App extends Component {state = {type:1}render() {return (<div><ul><li onClick={()=>{this.setState({type:1})}}>正在热映</li><li onClick={()=>{this.setState({type:2})}}>即将上映</li></ul><FilmList type={this.state.type}></FilmList></div>)}
}class FilmList extends Component{state = {list:[]}//初始化-执行一次componentDidMount() {// console.log(this.props.type)if(this.props.type===1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=6369301",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=2&k=8077848",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}UNSAFE_componentWillReceiveProps(nextProps){if(nextProps.type===1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=6369301",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=2&k=8077848",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}render(){return <ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>    )}</ul>}
}

销毁阶段

例如你在组件里写了一个定时器,即使组件删除了定时器也还在,就会降低性能,这时候就需要在销毁阶段销毁定时器

进行清理操作的生命周期函数

import { isCancel } from 'axios';
import React, { Component } from 'react';class App extends Component {state = {isCreated:false
}render() {return (<div><button onClick={() => {this.setState({isCreated:!this.state.isCreated})}}>click</button>{/* {this.state.isCreated?<Child></Child>:''} */}{this.state.isCreated&&<Child></Child>}</div>);}
}class Child extends Component {render() {return (<div>child</div>)}componentDidMount() {window.onresize = () => {console.log('resize')}//绑在window上的定时器,如果只卸载组件定时器还会运行this.timer=setInterval(() => {console.log('我是定时器')}, 1000);}componentWillUnmount() {console.log('componentWillUnmount') //销毁child组件的同时销毁事件监听和定时器clearInterval(this.timer)window.onresize=null}
}export default App;

新的生命周期的替代

修复旧生命周期函数的警告

getDerivedStateFromProps

初始化的时候代替componentWillMount,在ssr中 这个方法将会被多次调用, 所以会重复触发多遍,同时在这里如果绑定事件, 将无法解绑,导致内存泄漏 , 变得不够安全高效逐步废弃。

在后续更新的时候取代componentWillReceiveProps 外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求

该函数涵盖了初始化和更新阶段,适用于这两个阶段都重复执行的逻辑

第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子)

返回一个对象作为新的state,返回null则说明不需要在这里更新state

需要静态方法,返回一个对象

把传过来的state.myname转为首字母大写

import React, { Component } from 'react';class App extends Component {state = {myname: 'kerwin',myage:19}//componentWillMount 初始化static getDerivedStateFromProps(nextProps,nextState) {console.log('getDrivedStateFromProps',nextState)//在这个生命周期内做最后的修改,return的结果会把原来的state对象和返回的对象合并return {//实现首字母大写效果myname:nextState.myname.substring(0,1).toUpperCase()+nextState.myname.substring(1)}
}render() {return (<div><button onClick={() => {this.setState({myname:'heyefan'})}}>click</button>{/* 同名的覆盖掉,不同名的保留 */}app-{this.state.myname}-{this.state.myage}</div>);}
}export default App;

修改之前的案例:

import React, { Component } from 'react'
import axios from 'axios'
export default class App extends Component {state = {type:1}render() {return (<div><ul><li onClick={()=>{this.setState({type:1})}}>正在热映</li><li onClick={()=>{this.setState({type:2})}}>即将上映</li></ul><FilmList type={this.state.type}></FilmList></div>)}
}class FilmList extends Component{state = {list:[]}//初始化-执行一次componentDidMount() {// console.log(this.props.type)if(this.props.type===1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=6369301",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=2&k=8077848",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}static getDerivedStateFromProps(nextProps,nextState) {console.log('getDrivedStateFromProps',nextProps)//根据props和state的变化计算新的state,return的结果会把原来的state对象和返回的对象合并//此处不能执行异步请求,因为执行完会立马return,这样异步的结果就永远不会返回,也无法进行setState更新return {type:nextProps.type}}//通过this.setState把获取的数据转化为状态,配合componentDidUpdatecomponentDidUpdate(prevState) {//getDerivedStateFromProps做多次父子请求最后合并为一次,最后在此处处理console.log(this.state.type)if (this.state.type === prevState.type) {return}if(this.state.type===1){//请求卖座正在热映的数据console.log("请求卖座正在热映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=1&k=6369301",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}else{//请求卖座即将上映的数据console.log("请求卖座即将上映的数据")axios({url:"https://m.maizuo.com/gateway?cityId=110100&pageNum=1&pageSize=10&type=2&k=8077848",headers:{'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.0","e":"16395416565231270166529","bc":"110100"}','X-Host': 'mall.film-ticket.film.list'}}).then(res=>{console.log(res.data.data.films)this.setState({list:res.data.data.films})})}}render(){return <ul>{this.state.list.map(item=><li key={item.filmId}>{item.name}</li>    )}</ul>}
}

getSnapshotBeforeUpdate

实现定位重点功能:

willupdate记录高度

didupdate访问容器高度

scrollTop=此时容器高度-willupdate记录的高度

但是willupdate有副作用,在render的过程中容易被打断,在didupdate访问前有各种不可控事件可能发生,导致记录的高度不准

所以用getSnapshotBeforeUpdate(执行dom前的一刻拍了个shot)取代willupdate,来记录高度,所以必须有返回值

来邮件之后自动滚到之前对应邮件的高度
import React, { Component } from 'react';class App extends Component {state = {list: [1, 2, 3, 4, 5, 6, 7, 8, 9]}myref=React.createRef()getSnapshotBeforeUpdate() {//获取容器高度console.log(this.myref.current.scrollHeight)return this.myref.current.scrollHeight}componentDidUpdate(prevProps,prevState,value) {console.log(this.myref.current.scrollHeight)this.myref.current.scrollTop+=this.myref.current.scrollHeight-value}render() {return (<div><button onClick={() => {this.setState({list:[...[11,12,13,14,15,16],...this.state.list]})}}>来邮件</button><h1>邮箱应用</h1><div style={{height:'200px',overflow:'auto'}} ref={this.myref}><ul>{this.state.list.map(item => <li key={item} style={{ height: '100px', background: 'pink' }}>{item}</li>)}</ul></div></div>)}}export default App;

可以看到添加了几个邮件可以自动跳转到对应的高度

添加css文件以后可以更丝滑

react中性能优化的方案

1. shouldComponentUpdate

控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下, 需要进行优化。

2. PureComponent

在引入的时候替换:

import React, { PureComponent } from 'react';class ComponentName extends PureComponent {render() {return (<div>Content</div>);}
}export default ComponentName;

PureComponent会帮你 比较新props 跟 旧的props, 新的state和老的state(值相等,或者

对象含有相同的属性、且属性值相等 ),决定shouldcomponentUpdate 返回true 或者

false, 从而决定要不要呼叫 render function

注意:

如果你的 state props 『永远都会变』,那 PureComponent 并不会比较快,因为

shallowEqual 也需要花时间。

关键字:软件开发过程的五个阶段_免费动画模板素材网站_中国疫情最新消息_外贸网站模板

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: