资讯专栏INFORMATION COLUMN

React入门0x008: 生命周期

loonggg / 3057人阅读

0x000 概述

上一章说明了生命周期的概念,本质上就是框架在操作组件的过程中暴露出来的一系列钩子,我们可以选择我们需要的钩子,完成我们自己的业务,以下讲的是react v16.3以下的生命周期,v16.3以及以上的版本有所不同

0x001 组件挂载

以下是组件挂载的过程中触发的声明周期:

</>复制代码

  1. class App extends React.Component {
  2. constructor(props) {
  3. super(props)
  4. console.log("constructor", props)
  5. }
  6. componentWillMount() {
  7. console.log("componentWillMount")
  8. }
  9. componentDidMount() {
  10. console.log("componentDidMount")
  11. }
  12. render() {
  13. console.log("render")
  14. return

    {Date()}

  15. }
  16. componentDidMount() {
  17. console.log("componentDidMount")
  18. }
  19. }

0x002 组件更新

以下是组件更新的时候触发的生命周期:

</>复制代码

  1. class App extends React.Component {
  2. constructor() {
  3. super()
  4. this.state = {
  5. date: Date()
  6. }
  7. setTimeout(() => {
  8. this.setState({date: Date()})
  9. }, 3000)
  10. }
  11. componentWillReceiveProps() {
  12. console.log("componentWillReceiveProps")
  13. }
  14. shouldComponentUpdate() {
  15. console.log("shouldComponentUpdate")
  16. return true
  17. }
  18. render() {
  19. console.log("render")
  20. return

    {this.state.date}

  21. }
  22. componentWillUpdate() {
  23. console.log("componentWillUpdate")
  24. }
  25. componentDidUpdate() {
  26. console.log("componentDidUpdate")
  27. }
  28. }

第一次的render是由组件挂载引起的,而其他的方法则是由setState引起的

0x003 组件卸载

以下是由组件卸载的时候触发的生命周期:

</>复制代码

  1. class Content extends React.Component {
  2. render(){
  3. console.log("Content::render")
  4. return

    content

  5. }
  6. componentWillUnmount() {
  7. console.log("Content::componentWillUnmount")
  8. }
  9. }
  10. class App extends React.Component {
  11. constructor() {
  12. super()
  13. this.state = {
  14. show: true
  15. }
  16. setTimeout(() => {
  17. this.setState({show: false})
  18. }, 3000)
  19. }
  20. render() {
  21. console.log("App::render")
  22. return (
  23. this.state.show
  24. ?
  25. : null
  26. )
  27. }
  28. }

0x004 完整生命周期

</>复制代码

  1. 挂载:
  2. constructor
  3. componentWillMount
  4. render
  5. componentDidMount
  6. 更新:
  7. componentWillReceiveProps
  8. shouldComponentUpdate
  9. componentWillUpdate
  10. render
  11. componentDidUpdate
  12. 卸载:
  13. componentWillUnmount
  14. 错误处理(这里不说):
  15. componentDidCatch
0x005 声明周期使用场景

constructor(props)

</>复制代码

  1. 该方法主要用来初始化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 to this.state directly or define a state = {}; class property with the desired state in the App component.

</>复制代码

  1. class App extends React.Component {
  2. constructor() {
  3. super()
  4. this.state = {
  5. show: true
  6. }
  7. }
  8. render() {
  9. return (
  10. this.state.show
  11. ?
  12. : null
  13. )
  14. }
  15. }

componentWillMount()

</>复制代码

  1. 没啥卵用,可以在这个方法中调用setState(),并且设置的state可以在本次渲染生效,推荐使用constructor

render()

</>复制代码

  1. 你懂的,每次更新状态都会触发,但是不要在这里调用会触发组件更新的函数,比如setState(),否则可能陷入无尽阿鼻地狱。

componentDidMount()

</>复制代码

  1. 这个方法常用,触发这个生命周期,意味着dom和子组件都挂载好了,refs也可以用了,一般在这儿做网络请求。

componentWillReceiveProps(nextProps)

</>复制代码

  1. 这个组件也常用,一般用于父组件状态更新,导致传递给子组件的props更新,当时子组件又不是直接绑定父组件的props的时候使用,比如

</>复制代码

  1. class Content extends React.Component {
  2. constructor(props) {
  3. super(props)
  4. this.state = {
  5. content: props.content
  6. }
  7. }
  8. render() {
  9. return this.state.content
  10. }
  11. }
  12. class App extends React.Component {
  13. constructor() {
  14. super()
  15. this.state = {
  16. content: "1"
  17. }
  18. setTimeout(() => {
  19. this.setState({
  20. content: 10
  21. })
  22. }, 1000)
  23. }
  24. render() {
  25. return (
  26. )
  27. }
  28. }

我们接受父组件的state.content作为子组件的初始化state.content,但是1s 之后,父组件发生了变化,state.content从1变成了10,我们期望子组件也同时更新,可惜子组件的constructor只会执行一次,为了解决这个问题,我们可以添加这个生命周期:

</>复制代码

  1. class Content extends React.Component {
  2. constructor(props) {
  3. super(props)
  4. this.state = {
  5. content: props.content
  6. }
  7. }
  8. componentWillReceiveProps(nextProps) {
  9. this.setState({
  10. content:nextProps.content
  11. })
  12. }
  13. render() {
  14. return this.state.content
  15. }
  16. }

这样就可已在父组件props更新的时候,触发子组件的更新

shouldComponentUpdate(nextProps, nextState)

</>复制代码

  1. 这个组件也很常用,用来判断是否要进行某次更新,如果返回true则执行更新,如果返回false则不更新,常用与性能优化

</>复制代码

  1. class A extends React.Component {
  2. render() {
  3. console.log("A::render")
  4. return "A"
  5. }
  6. }
  7. class B extends React.Component {
  8. render() {
  9. console.log("B::render")
  10. return "A"
  11. }
  12. }
  13. class App extends React.Component {
  14. constructor(props) {
  15. super(props)
  16. this.state = {
  17. num: 1
  18. }
  19. setTimeout(() => {
  20. this.setState({
  21. num: 10,
  22. name: 1
  23. })
  24. })
  25. }
  26. render() {
  27. console.log("App::render")
  28. return
  29. {this.state.num}
  30. }
  31. }
  32. ReactDom.render(
  33. ,
  34. document.getElementById("app")
  35. )

我们在App组件中挂载了AB组件,App绑定了state.numAB绑定了state.name,然后在1s 后触发app组件的更新,此时查看浏览器,可以看到,APPAB都执行了render,但其实AB依赖的name并没有发生改变。如果是小组件还好,但如果是大组件,那就糟糕了,所以需要避免这种无所谓的更新:

</>复制代码

  1. class A extends React.Component {
  2. shouldComponentUpdate(nextProps, nextState) {
  3. return nextProps.name === this.props.name ? true : false
  4. }
  5. render() {
  6. console.log("A::render")
  7. return "A"
  8. }
  9. }
  10. class B extends React.Component {
  11. shouldComponentUpdate(nextProps, nextState) {
  12. return nextProps.name === this.props.name ? false : true
  13. }
  14. render() {
  15. console.log("B::render")
  16. return "A"
  17. }
  18. }

我在促发这个方法的时候,A组件返回 trueB 组件返回false,查看浏览器,可以发现,触发该方法的时候 A渲染了,而B没有渲染

componentWillUpdate(nextProps, nextState)

</>复制代码

  1. 没啥卵用,和componentDidUpdate组成一对儿,如果业务需要,就用

componentDidUpdate()

</>复制代码

  1. 没啥卵用,和componentWillUpdate组成一对儿,如果业务需要,就用

componentWillUnmount

</>复制代码

  1. 用于清理资源或者事件

</>复制代码

  1. class Content extends React.Component {
  2. constructor() {
  3. super()
  4. this.state = {
  5. num: 1
  6. }
  7. setInterval(() => {
  8. this.setState({
  9. num: ++this.state.num
  10. })
  11. console.log(this.state.num)
  12. }, 1000)
  13. }
  14. render() {
  15. return this.state.num
  16. }
  17. }
  18. class App extends React.Component {
  19. constructor() {
  20. super()
  21. this.state = {
  22. show: true
  23. }
  24. setTimeout(() => {
  25. this.setState({
  26. show: false
  27. })
  28. },2000)
  29. }
  30. render() {
  31. return this.state.show
  32. ?
  33. : null
  34. }
  35. }
  36. ReactDom
  37. .render(
  38. ,
  39. document
  40. .getElementById(
  41. "app"
  42. )
  43. )

我们在App组件中挂载Content组件,而Content组件则使用定时器每秒更新一次,但是在2s 之后,我们在App组件中卸载这个组件,但是,查看浏览器可以发现,定时器依旧在工作,并且报错:

</>复制代码

  1. 如果我们返回显示隐藏组件,就会积累越来越多的定时器。然后就爆炸了。
  2. ```
  3. class Content extends React.Component {
  4. constructor() {
  5. super()
  6. this.state = {
  7. num: 1
  8. }
  9. this.interval=setInterval(() => {
  10. this.setState({
  11. num: ++this.state.num
  12. })
  13. console.log(this.state.num)
  14. }, 1000)
  15. }
  16. render() {
  17. return this.state.num
  18. }
  19. componentWillUnmount(){
  20. clearInterval(this.interval)
  21. }
  22. }
  23. ```
  24. 这么解决
0x006 总结

在不同的生命周期做不同的事。

0x007 资源:

react

源码

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97082.html

相关文章

  • React入门0x007: 生命周期概念

    摘要:概述上一章只是稍微了解了一下和相关的简单用法,这一章需要讲一下组件的生命周期。生命周期的概念这玩意似乎很高大上,其实就是一个假概念罢了,直接来实现一个类似的吧。 0x000 概述 上一章只是稍微了解了一下state和setState相关的简单用法,这一章需要讲一下组件的生命周期。 0x001 生命周期的概念 这玩意似乎很高大上,其实就是一个假概念罢了,直接来实现一个类似的吧。大凡事物从...

    Blackjun 评论0 收藏0
  • Router入门0x201: 从 URL 到 SPA

    摘要:的全称是统一资源定位符英文,可以这么说,是一种标准,而网址则是符合标准的一种实现而已。渲染器,将组件渲染到页面上。 0x000 概述 从这一章开始就进入路由章节了,并不直接从如何使用react-route来讲,而是从路由的概念和实现来讲,达到知道路由的本质,而不是只知道如何使用react-route库的目的,毕竟react-route只是一个库,是路由的一个实现而已,而不是路由本身。 ...

    honmaple 评论0 收藏0
  • 快速入门React

    摘要:考虑到是快速入门,于是乎我们就记住一点,当修改值需要重新渲染的时候,的机制是不会让他全部重新渲染的,它只会把你修改值所在的重新更新。这一生命周期返回的任何值将会作为参数被传递给。 安装react npm install creat-react-app -gshowImg(https://segmentfault.com/img/remote/1460000015639868); 这里直...

    figofuture 评论0 收藏0
  • 01.react入门必备,知识点梳理,生命周期全讲解

    摘要:生命周期在版本中引入了机制。以后生命周期图解不包含官方不建议使用的事件处理事件的命名采用小驼峰式,而不是纯小写。只是在兄弟节点之间必须唯一受控组件使的成为唯一数据源。 react 基础 JSX JSX是一个 JavaScript 的语法扩展,可以很好地描述 UI 应该呈现出它应有交互的本质形式。 React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远...

    Jiavan 评论0 收藏0
  • React入门0x016: 访问Dom

    摘要:概述不到必要不要在中访问,尝试使用的思想去解决问题。当然,必要的时候还是可以的,比如某些依赖的组件时机在中,并不是任何时候都可以访问的,需要讲究时机。 0x000 概述 不到必要不要在React中访问Dom,尝试使用React的思想去解决问题。当然,必要的时候还是可以的,比如某些依赖Dom的组件 0x001 时机 在React中,并不是任何时候都可以访问Dom的,需要讲究时机。因为Re...

    NeverSayNever 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<