react组件

发布时间:2024年01月16日

一,组件使用的核心理念

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

二,组件的两种模型数据

2.1 props

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

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

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

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

2.2 state

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

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

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

三,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

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

文章来源:https://blog.csdn.net/wjs0406/article/details/135546025
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。