03_React 收集表单数据和 组件生命周期

news2024/9/24 19:17:17

React 收集表单数据和 组件生命周期

    • 一、收集表单数据
      • 1、例子
        • 1.1 需求:定义一个包含表单的组件,输入用户名密码后,点击登录提示输入信息
      • 2、理解:包含表单的组件分类
        • 2.1 受控组件
        • 2.2 非受控组件
    • 二、高阶函数\_函数柯里化
      • 1、复习--对象相关的知识
      • 2、高阶函数
      • 3、函数柯里化
      • 4、不用柯里化的写法
    • 三、组件的生命周期
      • 1、例子--引出生命周期
      • 2、理解
      • 3、生命周期(旧)
        • 3.1 挂载时(初始化)的流程
        • 3.2 更新时的流程
          • 3.2.1 流程线路 2(setState 流程)
          • 3.2.2 流程线路 3 (forceUpdate 流程)
          • 3.2.3 流程线路 1 (父组件 render 流程)
        • 3.3 总结生命周期(旧)
      • 4、对比新旧生命周期
        • 4.1 重要的钩子
        • 4.2 即将废弃的钩子
        • 4.3 getSnapshotBeforeUpdate的使用场景
        • 4.3 总结新的生命周期(常用的 render、ComponentDidMount、componentWillUnmount 是没有更改的)

一、收集表单数据

1、例子

1.1 需求:定义一个包含表单的组件,输入用户名密码后,点击登录提示输入信息
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>收集表单数据</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      class Login extends React.Component {
        render() {
          return (
            <form action="xxx" onSubmit={this.submit}>
              用户名:
              <input
                type="text"
                ref={(c) => {
                  this.username = c
                }}
                placeholder="用户名"
                name="username"
              />
              <br />
              密码:
              <input
                type="password"
                ref={(c) => {
                  this.password = c
                }}
                placeholder="密码"
                name="password"
              />
              <button>登录</button>
            </form>
          )
        }
        submit = (e) => {
          e.preventDefault()
          let { password, username } = this
          console.log(password.value, username.value)
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Login />, document.getElementById('test'))
    </script>
  </body>
</html>

2、理解:包含表单的组件分类

2.1 受控组件

页面中所有的输入类的节点,随着输入将数据维护到状态中,使用的时候直接从状态中取,就是受控组件
受控组件的优势在于 可以减少 ref 的使用

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>受控组件</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      class Login extends React.Component {
        // 初始化状态
        state = {
          username: '',
          password: '',
        }
        render() {
          return (
            <form action="xxx" onSubmit={this.submit}>
              用户名:
              <input
                type="text"
                onChange={this.saveUsername}
                placeholder="用户名"
                name="username"
              />
              <br />
              密码:
              <input
                type="password"
                onChange={this.savePassword}
                placeholder="密码"
                name="password"
              />
              <button>登录</button>
            </form>
          )
        }
        // 保存用户名到状态中
        saveUsername = (event) => {
          this.setState({ username: event.target.value })
        }
        // 保存密码到状态中
        savePassword = (event) => {
          this.setState({ password: event.target.value })
        }
        // 表单提交回调
        submit = (e) => {
          e.preventDefault()
          let { password, username } = this.state
          console.log(password, username)
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Login />, document.getElementById('test'))
    </script>
  </body>
</html>
2.2 非受控组件

页面中所有的输入类的节点,现用现取就是 非受控组件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>收集表单数据</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      class Login extends React.Component {
        render() {
          return (
            <form action="xxx" onSubmit={this.submit}>
              用户名:
              <input
                type="text"
                ref={(c) => {
                  this.username = c
                }}
                placeholder="用户名"
                name="username"
              />
              <br />
              密码:
              <input
                type="password"
                ref={(c) => {
                  this.password = c
                }}
                placeholder="密码"
                name="password"
              />
              <button>登录</button>
            </form>
          )
        }
        submit = (e) => {
          e.preventDefault()
          let { password, username } = this
          console.log(password.value, username.value)
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Login />, document.getElementById('test'))
    </script>
  </body>
</html>

二、高阶函数_函数柯里化

1、复习–对象相关的知识

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript">
      let a = 'name'
      let obj = {} // {name: 'Tom'}
      obj[a] = 'Tom'
      console.log(obj)
    </script>
  </body>
</html>

2、高阶函数

如果一个函数符合下面 2 个规范中任何一个,那么该函数就是高阶函数
1)若 A 函数,接收的参数是一个函数,那么 A 就可以称为高阶函数
2)若 A 函数,调用的返回值依然是一个函数,那么 A 就可以称之为高阶函数

常见的高阶函数: arr.map()、arr.filter()、Promise、arr.find()、arr.reduce()、setTimout 等等

下面代码中的 saveFormData 函数就是一个高阶函数,符合了条件 2(返回值是一个函数)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>高阶函数_函数柯里化</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      class Login extends React.Component {
        // 初始化状态
        state = {
          username: '',
          password: '',
        }
        render() {
          return (
            <form action="xxx" onSubmit={this.submit}>
              用户名:
              <input
                type="text"
                onChange={this.saveFormData('username')}
                placeholder="用户名"
                name="username"
              />
              <br />
              密码:
              <input
                type="password"
                onChange={this.saveFormData('password')}
                placeholder="密码"
                name="password"
              />
              <button>登录</button>
            </form>
          )
        }
        // 保存表单数据到状态中
        saveFormData = (dataType) => {
          // 把此函数交给 react 处理,react 可以传入一个 event
          return (event) => {
            console.log(dataType, event.target.value, this.state)
            this.setState({ [dataType]: event.target.value })
          }
          // this.setState({ type: event.target.value })
        }
        // 表单提交回调
        submit = (e) => {
          e.preventDefault()
          let { password, username } = this.state
          console.log(password, username)
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Login />, document.getElementById('test'))
    </script>
  </body>
</html>

3、函数柯里化

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
上一段代码中的 saveFormData 函数 就是一个函数柯里化

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>演示柯里化</title>
  </head>
  <body>
    <script type="text/javascript">
      function sum(a) {
        return (b) => {
          return (c) => {
            return a + b + c
          }
        }
      }
      console.log(sum(1)(12)(3))
    </script>
  </body>
</html>

4、不用柯里化的写法

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>不用函数柯里化的实现</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      class Login extends React.Component {
        // 初始化状态
        state = {
          username: '',
          password: '',
        }
        render() {
          return (
            <form action="xxx" onSubmit={this.submit}>
              用户名:
              <input
                type="text"
                onChange={(event) => {
                  this.saveFormData('username', event)
                }}
                placeholder="用户名"
                name="username"
              />
              <br />
              密码:
              <input
                type="password"
                onChange={(event) => {
                  this.saveFormData('password', event)
                }}
                placeholder="密码"
                name="password"
              />
              <button>登录</button>
            </form>
          )
        }
        // 保存表单数据到状态中
        saveFormData = (dataType, event) => {
          this.setState({ [dataType]: event.target.value })
        }
        // 表单提交回调
        submit = (e) => {
          e.preventDefault()
          let { password, username } = this.state
          console.log(password, username)
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Login />, document.getElementById('test'))
    </script>
  </body>
</html>

三、组件的生命周期

1、例子–引出生命周期

需求:自定义组件实现以下功能
1)让指定的文本做显示/隐藏 的渐变动画
2)从完全可见,到彻底消失,耗时 2s
3)点击 按钮 从界面卸载组件

挂载 mount
卸载 unMount

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>引出生命周期</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      // 1、创建组件
      // 生命周期回调函数《==》生命周期钩子函数《==》生命周期函数《==》生命周期钩子
      class Life extends React.Component {
        // 初始化状态
        state = {
          opacity: 1,
        }
        // render 调用的时机: 初始化渲染、状态更新之后
        render() {
          console.log('render')
          return (
            <div>
              <h2 style={{ opacity: this.state.opacity }}>
                React 学不会,咋可能啊
              </h2>
              <button onClick={this.deadHandle}>直接噶</button>
            </div>
          )
        }
        // componentDidMount 组件挂载完毕时调用
        componentDidMount() {
          console.log('componentDidMount')
          this.timer = setInterval(() => {
            let { opacity } = this.state
            opacity -= 0.1
            if (opacity <= 0) {
              opacity = 1
            }
            // console.log(opacity)
            this.setState({ opacity })
          }, 200)
        }
        // 组件将要卸载的时候调用
        componentWillUnmount() {
          // 清除定时器
          clearInterval(this.timer)
        }

        deadHandle = () => {
          // // 清除定时器
          // clearInterval(this.timer)
          // 卸载组件
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
          console.log('按钮点击,将组件直接卸载')
        }
      }
      // 2、渲染组件到页面
      // ReactDOM.render(组件,容器)
      ReactDOM.render(<Life />, document.getElementById('test'))
    </script>
  </body>
</html>

2、理解

1)组件对象从创建到死亡它会经历特定阶段
2)React 组件对象包含一系列钩子函数(生命周期回调函数),在特定的时刻调用
3)我们在定义组件时候,在特定的生命周期回调函数中做特定的工作

3、生命周期(旧)

react v16.8.0
在这里插入图片描述

3.1 挂载时(初始化)的流程

执行顺序:
Count—constructor
Count—componentWillMount
Count—render
Count—componentDidMount

卸载组件按钮点击后执行:
Count—componentWillUnmount

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      class Count extends React.Component {
        constructor(props) {
          console.log('Count---constructor')
          super(props)
          this.state = {
            num: 0,
          }
        }
        addHandle = () => {
          let { num } = this.state
          this.setState({ num: num + 1 })
        }
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log('Count---componentWillMount')
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log('Count---componentDidMount')
        }
        // 组件卸载时的钩子
        componentWillUnmount() {
          console.log('Count---componentWillUnmount')
        }
        render() {
          console.log('Count---render')
          let { num } = this.state
          return (
            <div>
              <h1>当前求和为 {num}</h1>
              <button onClick={this.addHandle}>点我+1</button>
              <button onClick={this.death}>卸载组件</button>
            </div>
          )
        }
      }
      ReactDOM.render(<Count />, document.getElementById('test'))
    </script>
  </body>
</html>
3.2 更新时的流程

在这里插入图片描述

3.2.1 流程线路 2(setState 流程)

正常更新:修改状态中的数据 组件能够更新

执行顺序
Count—shouldComponentUpdate
Count—componentWillUpdate
Count—render
Count—componentDidUpdate

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      class Count extends React.Component {
        constructor(props) {
          console.log('Count---constructor')
          super(props)
          this.state = {
            num: 0,
          }
        }
        addHandle = () => {
          let { num } = this.state
          this.setState({ num: num + 1 })
        }
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log('Count---componentWillMount')
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log('Count---componentDidMount')
        }
        // 组件卸载时的钩子
        componentWillUnmount() {
          console.log('Count---componentWillUnmount')
        }
        // 控制组件更新的“阀门”, 需要写一个返回值(类型为 boolean),返回false就不再更新
        shouldComponentUpdate() {
          console.log('Count---shouldComponentUpdate')
          return true
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log('Count---componentWillUpdate')
        }
        // 组件更新完毕的钩子
        componentDidUpdate() {
          console.log('Count---componentDidUpdate')
        }
        render() {
          console.log('Count---render')
          let { num } = this.state
          return (
            <div>
              <h1>当前求和为 {num}</h1>
              <button onClick={this.addHandle}>点我+1</button>
              <button onClick={this.death}>卸载组件</button>
            </div>
          )
        }
      }
      ReactDOM.render(<Count />, document.getElementById('test'))
    </script>
  </body>
</html>
3.2.2 流程线路 3 (forceUpdate 流程)

强制更新: 不修改状态中的数据但是想要更新页面就会用到。 阀门关闭也不会影响
执行顺序:
Count—componentWillUpdate
Count—render
Count—componentDidUpdate

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      class Count extends React.Component {
        constructor(props) {
          console.log('Count---constructor')
          super(props)
          this.state = {
            num: 0,
          }
        }
        addHandle = () => {
          let { num } = this.state
          this.setState({ num: num + 1 })
        }
        // 卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('test'))
        }
        // 强制更新按钮的回调
        force = () => {
          this.forceUpdate()
        }
        // 组件将要挂载的钩子
        componentWillMount() {
          console.log('Count---componentWillMount')
        }
        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log('Count---componentDidMount')
        }
        // 组件卸载时的钩子
        componentWillUnmount() {
          console.log('Count---componentWillUnmount')
        }
        // 控制组件更新的“阀门”, 需要写一个返回值(类型为 boolean),返回false就不再更新
        shouldComponentUpdate() {
          console.log('Count---shouldComponentUpdate')
          return true
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log('Count---componentWillUpdate')
        }
        // 组件更新完毕的钩子
        componentDidUpdate() {
          console.log('Count---componentDidUpdate')
        }
        render() {
          console.log('Count---render')
          let { num } = this.state
          return (
            <div>
              <h1>当前求和为 {num}</h1>
              <button onClick={this.addHandle}>点我+1</button>
              <button onClick={this.death}>卸载组件</button>
              <button onClick={this.force}>
                不更改任何状态的数据,强制更新一下
              </button>
            </div>
          )
        }
      }
      ReactDOM.render(<Count />, document.getElementById('test'))
    </script>
  </body>
</html>
3.2.3 流程线路 1 (父组件 render 流程)

执行顺序:
Child—render
Child—componentWillReceiveProps {carName: ‘奥迪’}
Child—shouldComponentUpdate
Child—componentWillUpdate
Child—render
Child—componentDidUpdate

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      class Parent extends React.Component {
        // 初始化状态
        state = {
          carName: '奔驰',
        }
        changeCar = () => {
          this.setState({ carName: '奥迪' })
        }

        render() {
          let { carName } = this.state
          return (
            <div>
              Parent, 我是父组件
              <button onClick={this.changeCar}>换车</button>
              <Child carName={carName} />
            </div>
          )
        }
      }
      class Child extends React.Component {
        // 组件将要接收新的prps 的钩子第一次传的不算, 之后的就能够执行,还能够接收到props参数
        componentWillReceiveProps(props) {
          console.log('Child---componentWillReceiveProps', props)
        }
        // 控制组件更新的“阀门”, 需要写一个返回值(类型为 boolean),返回false就不再更新
        shouldComponentUpdate() {
          console.log('Child---shouldComponentUpdate')
          return true
        }
        // 组件将要更新的钩子
        componentWillUpdate() {
          console.log('Child---componentWillUpdate')
        }
        // 组件更新完毕的钩子
        componentDidUpdate() {
          console.log('Child---componentDidUpdate')
        }
        render() {
          console.log('Child---render')
          return <div>Child, 我是子组件,接收到的车是{this.props.carName}</div>
        }
      }

      ReactDOM.render(<Parent />, document.getElementById('test'))
    </script>
  </body>
</html>
3.3 总结生命周期(旧)

生命周期的三个阶段
**1、初始化阶段:**由 ReactDom.render() 触发—初次渲染
constructor()
componentWillMount()
render()
componentDidMount() ====》常用,一般再这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
**2、更新阶段:**由组件内部 this.setState() 或父组件重新 render 触发
shouldComponentUpdate()
componentWillUpdate()
render() =======>必须
componentDidUpdate()
**3、卸载组件:**由 ReactDOM.unmountComponentAtNode() 触发
componentWillUnmount() ====》常用,一般再这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

4、对比新旧生命周期

新的生命周期即将不再维护componentWillMount、componentWillUpdate、
新增 getDerivedStateFromProps、getSnapshotBeforeUpdate,但是不是替代之前前面丢弃的钩子,这两个新的钩子基本不用

React v18.3.0
在这里插入图片描述

4.1 重要的钩子

render:初始化渲染或更新渲染调用
ComponentDidMount:开启监听,发送 ajax请求
componentWillUnmount:做一些收尾工作,如:清理定时器

4.2 即将废弃的钩子

omponentWillMount
componentWillUpdate
componentWillUnmount

4.3 getSnapshotBeforeUpdate的使用场景
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>生命周期(新)</title>
    <style>
    .list {
      width: 200px;
      height: 150px;
      background-color: skyblue;
      overflow-y: auto;
  }
  .news {
      height: 30px;
  }
</style>
  </head>
  <body>
    <div id="test"></div>
    <!-- 引入 react 核心库 -->
    <script type="text/javascript" src="../js/v18.3.0/react.development.js"></script>
    <!-- 引入 react-dom,用于支持 react 操作DOM -->
    <script
      type="text/javascript"
      src="../js/v18.3.0/react-dom.development.js"
    ></script>
    <!-- 引入babel, 用于将 jsx 转为 js -->
    <script type="text/javascript" src="../js/v18.3.0/babel.min.js"></script>

    <!-- 引入 prop-types,用于对组件标签属性进行限制, 存在 PropTypes -->
    <script type="text/javascript" src="../js/v18.3.0/prop-types.js"></script>

    <!-- 此处一定要写babel -->
    <script type="text/babel">
      class NewsList extends React.Component {
        state = {
          newArr:[]
        }
        componentDidMount(){
          this.timer = setInterval(()=>{
            const {newArr} = this.state
            let news = '新闻'+(newArr.length+1)
            this.setState({
              newArr: [news, ...newArr]
            })
          },1000)
        }
        // 在更新之前获取快照
        getSnapshotBeforeUpdate(){
          console.log("getSnapshotBeforeUpdate", this.refs.list.scrollHeight)
          return this.refs.list.scrollHeigh
        }
        componentDidUpdate(prePops, preState, height){
          this.refs.list.scrollTop += this.refs.list.scrollHeight-height
        }
        render() {
          console.log('Count---render')
          return (
            <div className="list" ref='list'>
              {this.state.newArr.map((el,inx)=>{
                return <div className="news" key={inx}>{el}</div>
              })}
              
          </div>
          )
        }
      }
      ReactDOM.render(<NewsList />, document.getElementById('test'))
    </script>
  </body>
</html>

4.3 总结新的生命周期(常用的 render、ComponentDidMount、componentWillUnmount 是没有更改的)

**1、初始化阶段:**由 ReactDom.render() 触发—初次渲染
constructor()
getDerivedStateFromProps()
render()
componentDidMount() ====》常用,一般再这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
**2、更新阶段:**由组件内部 this.setState() 或父组件重新 render 触发
getDerivedStateFromProps
shouldComponentUpdate()
render() =======>必须
getSnapshotBeforeUpdate()
componentDidUpdate()
**3、卸载组件:**由 ReactDOM.unmountComponentAtNode() 触发
componentWillUnmount() ====》常用,一般再这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070717.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB 手动实现点云投影滤波器 (76)

点云投影到邻近的精确拟合平面,减少噪声点,此为投影滤波器 MATLAB 手动实现点云投影滤波器(76) 一、投影滤波器简介二、实现步骤二、算法实现1.代码2.效果这里用到的投影方法和平面拟合方法以及生成平面方法都在以往文章有所实现,有兴趣可参考: MATLAB点云处理总目录 一…

Paimon Flink本地读取数据报错

1.idea本地读取paimon 用idea在本地读取paimon的表时需要添加的依赖除了官网提出的和hadoop相关的&#xff0c;paimon-flink之类相关的除外还需要其他额外依赖 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.tabl…

大模型从入门到精通——词向量及知识库介绍

词向量及知识库介绍 1.词向量 1.1 什么是词向量 词向量是一种将单词表示为实数向量的方式。每个单词通过一个高维向量来表示&#xff0c;向量的每一维都是一个实数&#xff0c;这些向量通常位于一个高维空间中。词向量的目标是将语义相似的单词映射到相邻的向量空间中&#…

【STM32 HAL】多串口printf重定向

【STM32 HAL】多串口printf重定向 前言单串口printf重定向原理实现CubeMX配置Keil5配置 多串口printf重定向 前言 在近期项目中&#xff0c;作者需要 STM32 同时向上位机和手机发送数据&#xff0c;传统的 printf 重定向只能输出到一个串口。本文介绍如何实现 printf 同时输出…

回归预测|基于北方苍鹰优化混合核极限学习机的数据预测Matlab程序NGO-HKELM 多特征输入单输出

回归预测|基于北方苍鹰优化混合核极限学习机的数据预测Matlab程序NGO-HKELM 多特征输入单输出 文章目录 前言回归预测|基于北方苍鹰优化混合核极限学习机的数据预测Matlab程序NGO-HKELM 多特征输入单输出 一、NGO-HKELM 模型1. NGO&#xff08;北方苍鹰优化算法&#xff09;2. …

DRF——pagination分页模块

文章目录 分页继承APIView类用法1.PageNumberPagination2.LimitOffsetPagination3.CursorPagination 继承GenericAPIView派生类用法1.PageNumberPagination2.LimitOffsetPagination3.CursorPagination 分页 在查看数据列表的API中&#xff0c;如果 数据量 比较大&#xff0c;肯…

RSA非对称性加密02: 加密redis的连接密码(下)

全文目录,一步到位 1.前言简介1.1 专栏传送门1.1.2 上文传送门 2. 使用方式2.1 使用druid自带的RSA加密工具2.1.1 引入druid依赖2.1.2 原yml配置(对比使用)2.1.2 新yml配置 2.2 springboot的redis配置类2.2.1 例如在RedisConfig中2.2.2 设置序列化与反序列化代码示例如下: 2.3 …

初始redis:Zset有序集合

Set作为集合&#xff0c;有两个特点&#xff1a;唯一且无序。 Zset是有序集合&#xff0c;在保证唯一的情况下&#xff0c;是根据什么来排序的呢&#xff1f;排序的规则是什么&#xff1f; Zset中的member引入了一个属性&#xff0c;分数&#xff08;score&#xff09;&#…

写SCI能用上的AI论文写作工具!码住!

01 Quillbot 提供改写、语法检查、抄袭检测、摘要生成、引文生成等功能。它可以在各种喜欢的网站上使用&#xff0c;帮助用户轻松提高写作效率和质量。 02梅子AI论文 1智能AI论文神器-查重率10%左右-参考文献致谢模板查重报告一键打包 无限免费生成千字论文大纲-在线快速生成…

智慧园区可视化:智能管理与高效运营的未来

图扑 GIS 智慧园区可视化系统整合地理信息和数据分析&#xff0c;实现全方位智能管理&#xff0c;优化资源调度&#xff0c;提高运营效率&#xff0c;保障园区安全和用户满意度。

数据结构【链试结构二叉树】

&#x1f31f;个人主页&#xff1a;落叶 目录 ​编辑 实现链式结构⼆叉树 前中后序遍历&#xff1a; 遍历规则 代码实现 前序遍历&#xff1a; 中序遍历&#xff1a; 后序遍历&#xff1a; 图解遍历&#xff1a; 函数递归栈帧图&#xff1a; 结点个数以及高度等 【⼆…

【生日视频制作】教师节中秋节国庆节奔驰大G汽车车身AE模板修改文字软件生成器教程特效素材【AE模板】

奔驰大G汽车身生日视频制作教程AE模板修改字软件生成器素材 怎么如何做的【生日视频制作】教师节中秋节国庆节奔驰大G汽车车身AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频…

iOS工程:获取手机相册权限,iOS原生系统弹窗, Privacy隐私政策选择,如何添加系统弹出并修改描述文字

【iOS工程】获取手机相册权限&#xff0c;iOS原生系统弹窗, Privacy隐私政策选择&#xff0c;如何添加系统弹出并修改描述文字 设备/引擎&#xff1a;Mac&#xff08;11.6&#xff09;/Mac Mini 开发工具&#xff1a;Xcode&#xff08;15.0.1&#xff09; 开发需求&#xff…

maven Tomcat插件安装 运行web项目 (3)

1.maven工程目录结构 main是用来写我们程序 test是用来测试 java是源程序 resource是配置 maven项目构建命令 2.配置maven 创建Maven工程 这里的项目名称可以随便取 进来后改成自己想要的jdk

天津市2024年成人高考报名须知

&#x1f6a7;天津市2024年成人高考报名须知 &#x1f32b;2024年天津市成人高校招生考试报名。符合天津市报名条件的在职从人员和社会其他人员&#xff0c;可报名参加全国各类成人高等学校招生统一考试。考生须在规定时间完成报名&#xff0c;逾期不再补报。 &#x1f32b;网上…

微服务事务管理

1.分布式事务问题 1.1.本地事务 本地事务&#xff0c;也就是传统的单机事务&#xff0c;在传统数据库事务中&#xff0c;必须要满⾜四个原则&#xff1a; 1.2.分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构下&#xff0c;产⽣的事务&#xff0c;例…

使用itextpdf5.x将网页转为PDF,并添页眉页脚页码

一、用到的Maven依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version></dependency><!-- 中文字体支持 --><dependency><groupId>com.itextpdf…

Gameplay Ability System(通过表配置不同等级的伤害)

一、创建配置表 1、创建Excel表格&#xff0c;输入数据&#xff0c;表示1级的普攻伤害为5&#xff1b;2级的普攻伤害为15。 2、另存为.csv格式文件。 3、当然也可以通过记事本直接写成下图这样。 二、导入UE5处理 1、导入为CurveTable的稳定格式&#xff0c;命名为CT_MeleeA…

探索厦门凯酷全科技有限公司抖音小店的实用魅力

在数字化浪潮汹涌的今天&#xff0c;电商平台如雨后春笋般涌现&#xff0c;而抖音作为短视频与电商融合的佼佼者&#xff0c;更是为众多企业开辟了新的营销与销售渠道。厦门凯酷全科技有限公司&#xff0c;作为这股潮流中的一股清流&#xff0c;凭借其独特的产品定位与创新的营…

【网络】传输层协议——UDP协议

1.传输层协议 首先我们要明白&#xff0c;进入传输层&#xff0c;也就进入了操作系统内核。 因为应用层下面这几个就是操作系统内部 我们学传输层及其以下几层&#xff0c;也就是在学操作系统内核的网络模块。 1.1.传输层协议 传输层能够实现端到端的连接。比如说我们用QQ与…