上一章说明了生命周期的概念,本质上就是框架在操做组件的过程当中暴露出来的一系列钩子,咱们能够选择咱们须要的钩子,完成咱们本身的业务,如下讲的是react v16.3
如下的生命周期,v16.3
以及以上的版本有所不一样react
如下是组件挂载的过程当中触发的声明周期:git
class App extends React.Component { constructor(props) { super(props) console.log('constructor', props) } componentWillMount() { console.log('componentWillMount') } componentDidMount() { console.log('componentDidMount') } render() { console.log('render') return <p>{Date()}</p> } componentDidMount() { console.log('componentDidMount') } }
如下是组件更新的时候触发的生命周期:github
class App extends React.Component { constructor() { super() this.state = { date: Date() } setTimeout(() => { this.setState({date: Date()}) }, 3000) } componentWillReceiveProps() { console.log('componentWillReceiveProps') } shouldComponentUpdate() { console.log('shouldComponentUpdate') return true } render() { console.log('render') return <p>{this.state.date}</p> } componentWillUpdate() { console.log('componentWillUpdate') } componentDidUpdate() { console.log('componentDidUpdate') } }
第一次的render
是由组件挂载引发的,而其余的方法则是由setState
引发的浏览器
如下是由组件卸载的时候触发的生命周期:性能优化
class Content extends React.Component { render(){ console.log('Content::render') return <p>content</p> } componentWillUnmount() { console.log('Content::componentWillUnmount') } } class App extends React.Component { constructor() { super() this.state = { show: true } setTimeout(() => { this.setState({show: false}) }, 3000) } render() { console.log('App::render') return ( this.state.show ? <Content/> : null ) } }
挂载: constructor componentWillMount render componentDidMount 更新: componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate 卸载: componentWillUnmount 错误处理(这里不说): componentDidCatch
constructor(props)
:网络
该方法主要用来初始化state
,或者初始化一些资源,能够访问prop
,可是访问不了setState
,会报错:Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign tothis.state
directly or define astate = {};
class property with the desired state in the App component.
class App extends React.Component { constructor() { super() this.state = { show: true } } render() { return ( this.state.show ? <Content/> : null ) } }
componentWillMount()
app
没啥卵用,能够在这个方法中调用setState()
,而且设置的state
能够在本次渲染生效,推荐使用constructor
render()
框架
你懂的,每次更新状态都会触发,可是不要在这里调用会触发组件更新的函数,好比
setState()
,不然可能陷入无尽阿鼻地狱。
componentDidMount()
dom
这个方法经常使用,触发这个生命周期,意味着dom
和子组件都挂载好了,refs
也能够用了,通常在这儿作网络请求。
componentWillReceiveProps(nextProps)
函数
这个组件也经常使用,通常用于父组件状态更新,致使传递给子组件的props
更新,当时子组件又不是直接绑定父组件的props
的时候使用,好比
class Content extends React.Component { constructor(props) { super(props) this.state = { content: props.content } } render() { return this.state.content } } class App extends React.Component { constructor() { super() this.state = { content: "1" } setTimeout(() => { this.setState({ content: 10 }) }, 1000) } render() { return ( <Content content={this.state.content}/> ) } }
咱们接受父组件的state.content
做为子组件的初始化state.content
,可是1s 以后,父组件发生了变化,state.content
从1变成了10,咱们指望子组件也同时更新,惋惜子组件的constructor
只会执行一次,为了解决这个问题,咱们能够添加这个生命周期:
class Content extends React.Component { constructor(props) { super(props) this.state = { content: props.content } } componentWillReceiveProps(nextProps) { this.setState({ content:nextProps.content }) } render() { return this.state.content } }
这样就可已在父组件props
更新的时候,触发子组件的更新
shouldComponentUpdate(nextProps, nextState)
这个组件也很经常使用,用来判断是否要进行某次更新,若是返回true
则执行更新,若是返回false
则不更新,经常使用与性能优化
class A extends React.Component { render() { console.log("A::render") return "A" } } class B extends React.Component { render() { console.log("B::render") return "A" } } class App extends React.Component { constructor(props) { super(props) this.state = { num: 1 } setTimeout(() => { this.setState({ num: 10, name: 1 }) }) } render() { console.log("App::render") return <div> <A name={this.state.name}/> <B name={this.state.name}/> <div> {this.state.num} </div> </div> } } ReactDom.render( <App></App>, document.getElementById('app') )
咱们在App
组件中挂载了A
、B
组件,App
绑定了state.num
,A
、B
绑定了state.name
,而后在1s 后触发app
组件的更新,此时查看浏览器,能够看到,APP
、A
、B
都执行了render
,但其实A
、B
依赖的name
并无发生改变。若是是小组件还好,但若是是大组件,那就糟糕了,因此须要避免这种无所谓的更新:
class A extends React.Component { shouldComponentUpdate(nextProps, nextState) { return nextProps.name === this.props.name ? true : false } render() { console.log("A::render") return "A" } } class B extends React.Component { shouldComponentUpdate(nextProps, nextState) { return nextProps.name === this.props.name ? false : true } render() { console.log("B::render") return "A" } }
我在促发这个方法的时候,A
组件返回 true
,B
组件返回false
,查看浏览器,能够发现,触发该方法的时候 A
渲染了,而B
没有渲染
componentWillUpdate(nextProps, nextState)
没啥卵用,和
componentDidUpdate
组成一对儿,若是业务须要,就用
componentDidUpdate()
没啥卵用,和
componentWillUpdate
组成一对儿,若是业务须要,就用
componentWillUnmount
用于清理资源或者事件
class Content extends React.Component { constructor() { super() this.state = { num: 1 } setInterval(() => { this.setState({ num: ++this.state.num }) console.log(this.state.num) }, 1000) } render() { return this.state.num } } class App extends React.Component { constructor() { super() this.state = { show: true } setTimeout(() => { this.setState({ show: false }) },2000) } render() { return this.state.show ? <Content/> : null } } ReactDom .render( <App></App>, document .getElementById( 'app' ) )
咱们在App
组件中挂载Content
组件,而Content
组件则使用定时器每秒更新一次,可是在2s 以后,咱们在App
组件中卸载这个组件,可是,查看浏览器能够发现,定时器依旧在工做,而且报错:
若是咱们返回显示隐藏组件,就会积累愈来愈多的定时器。而后就爆炸了。 ``` class Content extends React.Component { constructor() { super() this.state = { num: 1 } this.interval=setInterval(() => { this.setState({ num: ++this.state.num }) console.log(this.state.num) }, 1000) } render() { return this.state.num } componentWillUnmount(){ clearInterval(this.interval) } } ``` 这么解决
在不一样的生命周期作不一样的事。