react组件

一,组件使用的核心理念

定义组件时,应尽量保持组件功能的单一性,也就是一个组件只做一件事。

二,组件的两种模型数据

2.1 props

作用(传递数据):props的主要用作是父组件向子组件传递数据,来定制子组件的展示

实现:通过向子组件设置props属性={属性值} 实现;子组件在入参处接收属性,同时可以设置默认值(eg:function Avatar({ size = 100 }) {...})

注意:props子组件接受属性的默认值,仅在缺少props和设置 props属性={undefined}时才生效,如果设置 props属性={null}、props属性={0}这种假值不会生效

扩展:接收的参数可以是展开语法...props传递所有的props数据(eg:<Avatar {...props} />),但是不建议过度使用。

2.2 state

作用(修改数据):state的主要用作是在内存中保存信息,用来后续追踪与更新数据

实现:通过内置的HOOK函数useState 实现

注意

(1)state的使用需要尽量保持他不自我重复(例如一个数组列表,他即用于A处展示,也用于B处操作修改,尽量定义一次,不要copy多个)

(2)每一次渲染state的值都是固定的,修改后的state值下一次渲染才改变(react会等到事件处理函数中的所有代码都都运行完毕再处理你的state更新。例如:

export default function Counter() {
  const [number, setNumber] = useState(0); // number初始值为0

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1); // 修改下一次渲染number的值,为0 + 1
        alert(number); // 弹出0,下一次渲染number才会变成1
      }}>+3</button>
    </>
  )
}

扩展:如果想在下次渲染前多次更新同一个state(不常用),可以像setNumber(n => n + 1) 这样传入一个state的更新函数(react会将该函数添加到队列中,以便在事件处理函数中的所有其他代码运行后进行处理),而不是像 setNumber(number + 1)这样传入下一个state 值

三,state的反向数据流

由于react是单向数据流,通常数据是右上到下传入,但子组件修改state数据后,需要告知父组件更新state。他的实现方式与vue的$emit异曲同工,在子组件的引用上处自定义事件(onXXXChange)事件中可以调用useState的set方法来修改值;子组件通过onChange事件来触发自定义事件的调用

示例:

// 父组件
function FilterableProductTable({ products }) {
    const [filterText, setFilterText] = useState(''); // 定义state
    // 定义子组件透传的自定义change事件onFilterTextChange
    return (
        <div>
          <SearchBar
            filterText={filterText}
            onFilterTextChange={setFilterText} />
        </div>
    )
}

// 子组件
function SearchBar ({filterText}) {
    return (<input
          type="text"
          value={filterText}
          placeholder="Search..."
          onChange={(e) => onFilterTextChange(e.target.value)} />
    )
}

四,props传递子组件

有时候可能用组件嵌套组件,例如vue中的slot功能。react中依然用props,与普通属性不同的是:

(1)定义被嵌套的组件时,props入参接收一个children,并将其包裹在div中渲染(可与vue的slot对比理解,react中自己封装被slot的组件)

// 在Card组件中传入一个子组件,则接收参数children
function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

(2)被嵌套的组件引用处,直接包裹要嵌套的目标组件(可与vue的slot对比理解,react中少了一个slot参数)

export default function Profile() {
 // 要把Avatar组件嵌套入Card组件中
  return (
    <Card>
      <Avatar
        size={100}
        person={
  { 
          name: 'Katsuko Saruhashi',
          imageId: 'YfeOqp2'
        }}
      />
    </Card>
  );
}

五,组件纯粹原则

开发组件要尽量保证组件的纯粹原则,这样可以安全的缓存他们也可以避免以后迭代带来的各种Bug。即保证组件像一个数学公式,只要输入一样,输出就永远一致。类似于以下这种示例,就是不纯粹的组件:

function Cup() {
  guest = guest + 1;
  return <h2>Tea cup for guest #{guest}</h2>;
}

六,类(class)组件的生命周期

概念:组件实例从被创建到被销毁的过程称为组件的生命周期。这里大概了解,详细了解与图解可参考React 生命周期详解 - 掘金

class类组件中,每一次由状态改变导致页面视图的改变,都经过了两个阶段:render阶段和commit阶段。由class类组件创建的实例拥有的生命周期,在render阶段执行他的render函数,和DOM节点的diff算法,找出需要改变的DOM操作在commit阶段将要改变的DOM操作提交至视图中

首次渲染页面时,会调用mount相关的生命周期钩子

之后的页面渲染中,会调用Update相关的生命周期钩子;

因此mount相关的生命周期钩子只调用一次。

render阶段(初始化阶段)

  • constructor:构造函数(mount相关,只执行一次)。在初始化实例的时候调用,返回一个组件实例。

                          应用场景:通常用来初始化组件的state

  • getDerivedStateFromProps:(不常用)(mount、update)从更新后的props中获取State,它让组件在 props发生改变时更新它自身的内部state。
  • shouldComponentUpdate:(update)判断一个组件是否应该更新。在组件准备更新之前调用。它接收两个参数,nextProps和nextState,即下一次更新的props和state。

                          应用场景:通常用来做性能优化

  • render组件中唯一必须实现的方法(mount、update)。它的返回值将作为页面渲染的视图。返回类型有:

                                        (1)JSX语法的React 元素

                                        (2)数组返回的多个元素

                                        (3)字符串、数值文本节点

                                        (4)boolean类型或者null什么都不渲染

                                        (5)Portals:渲染子节点到不同的子树中

commit阶段(运行中阶段)

  • componentDidMount:(mount相关,只执行一次)将组件对应的DOM插入DOM 树中之后、浏览器更新视图之前调用

                  应用场景:通常用做依赖DOM的初始化操作、发送网络请求、订阅。

  • getSnapshotBeforeUpdate:(update)在最近一次渲染提交至DOM树之前执行。

                  应用场景:此时DOM树还未改变,可以获取DOM改变前的信息

  • componentDidUpdate:(update)在组件更新后立即调用。首次渲染不会调用该方法,但是执行时机与componentDidMount一致。他接收三个参数,分别是 prevProps、prevState、snapshot,即前一个状态的props,前一个状态的state、getSnapshotBeforeUpdate的返回值。

                 应用场景:可以对DOM进行操作,也可以进行网络请求。

  • componentWillUnmount:(Unmount)在组件卸载以及销毁之前调用。

                 应用场景:通常用来执行组件的清理操作。例如:清除 timer、取消网络请求、清除订阅等。

注意

  • shouldComponentUpdate钩子如果返回false,则render 阶段后续生命周期钩子(render方法)不会执行
  • getDerivedStateFromProps钩子是静态方法,因此不能使用this获取到组件实例

七,父子组件的生命周期执行顺序

7.1 首次渲染时的执行顺序

示例组件:父组件A、子组件B、子组件C,首次渲染

(1)依次执行父组件A的render阶段的mount相关的钩子constructor、getDerivedStateFromPro

ps、render

(2)依次执行子组件B的render阶段的mount相关的钩子(...同上)

(3)依次执行子组件C的render阶段的mount相关的钩子(...同上)

(4)执行子组件B的commit阶段update相关的钩子componentDidMount

(4)执行子组件C的commit阶段update相关的钩子componentDidMount

(4)执行父组件A的commit阶段update相关的钩子componentDidMount

7.2 子组件状态改变的执行顺序

示例组件:父组件A、子组件B、子组件C。  改变B子组件的某个状态

(1)执行B子组件的钩子:getDerivedStateFromProps

(2)执行B子组件的update相关的钩子:shouldComponentUpdate

(3)执行B子组件的钩子:render

(4)执行B子组件的update相关的钩子:getSnapshotBeforeUpdate

(5)执行B子组件的update相关的钩子:componentDidUpdate

说明:子组件的状态改变,只会执行当前子组件的生命周期函数

7.3 父组件状态改变的执行顺序

示例组件:父组件A、子组件B、子组件C。  改变A父组件的某个状态

(1)执行父组件render阶段的生命周期钩子:getDerivedStateFromProps、shouldComponentUp

date、render

(2)执行B子组件render阶段的生命周期钩子:getDerivedStateFromProps、shouldComponent

Update、render

(3)执行C子组件render阶段的生命周期钩子:getDerivedStateFromProps、shouldComponent

Update、render

(4)执行B子组件的getSnapshotBeforeUpdate

(5)执行C子组件的getSnapshotBeforeUpdate

(6)执行A父组件的getSnapshotBeforeUpdate

(7)执行B子组件的componentDidUpdate

(8)执行C子组件的componentDidUpdate

(9)执行A父组件的componentDidUpdate

说明:父组件某状态的改变,会将父组件和其所有子组件的部分生命周期钩子都触发执行一遍

相关推荐

  1. ReactReact API

    2024-01-17 12:58:02       21 阅读
  2. react

    2024-01-17 12:58:02       35 阅读
  3. react:profiler

    2024-01-17 12:58:02       10 阅读
  4. react :Suspense

    2024-01-17 12:58:02       16 阅读
  5. react:strictmode

    2024-01-17 12:58:02       15 阅读
  6. react:fragment

    2024-01-17 12:58:02       12 阅读
  7. React.memo

    2024-01-17 12:58:02       26 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-17 12:58:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-17 12:58:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-17 12:58:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-17 12:58:02       18 阅读

热门阅读

  1. React16源码: React中的performWork的源码实现

    2024-01-17 12:58:02       25 阅读
  2. Flutter系列:Flutter常见问答(可用于面试)

    2024-01-17 12:58:02       31 阅读
  3. 【架构设计】单体软件向微服务化演变

    2024-01-17 12:58:02       38 阅读
  4. 算法训练营Day41

    2024-01-17 12:58:02       35 阅读
  5. 华为认证云计算专家(HCIE-Cloud Computing)--练习题

    2024-01-17 12:58:02       28 阅读
  6. 配置DNS主从服务器,能够实现正常的正反向解析

    2024-01-17 12:58:02       34 阅读
  7. SpringBoot+Vue实现一个系统登录功能

    2024-01-17 12:58:02       38 阅读