今天你学了吗?必知道的react知识点

177 阅读7分钟

「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

Hope is a good thing, maybe the best of things. And no good thing ever dies.

核心概念

  • JSX 语法 是一个 JavaScript 的语法扩展,React语法糖。 Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。

  • 组件

    • class组件
      • React.Component或者React. PureComponent 创建
      • 可以使用生命周期函数
      • handle事件(自定义的方法)需要绑定this,否则this就是undefined(class 类不管是原型方法还是静态方法定义,“this”值在被调用的函数内部将为 undefined)
    • React.Component或者React. PureComponent 创建
      • constructor
        • 定义state
        • 调用super(props),组件使用props
      • 可以使用生命周期函数
      • this绑定
        • handle事件(自定义的方法)需要绑定this,否则this就是undefined
        • class 类不管是原型方法还是静态方法定义,“this”值在被调用的函数内部将为 undefined
        • 通常在在constructor中进行绑定this
      • 可以使用this.state和this.props
    • 函数式组件
      • 无生命周期函数
      • 使用useState()钩子定义state
      • 无this
        • 经过Babel翻译的结果
        • Babel是严格模式‘use strict’下进行的,不允许函数里的this指向window,所以这里指向undefined
  • state

    • 组件本身的状态
    • state变化会触发组件重新渲染
  • props

    • 组件的“只读”属性
    • 组件的props发生变化触发组件重新渲染
  • 生命周期(Class组件)

    • 废弃组件生命周期图谱
      • componentWillUpdate()
        • 可以使用 UNSAFE_componentWillUpdate()
      • componentWillReceiveProps()
        • 可以使用 UNSAFE_componentWillReceiveProps()
      • componentWillMount()
        • 可以使用 UNSAFE_componentWillMount()
    • 挂载
      • constructor()
        • constructor(props) {
            super(props);
              // 不要在这里调用 this.setState()
              this.state = { counter: 0 };
              this.handleClick = this.handleClick.bind(this);
            }
          
        • 在 React 组件挂载之前,会调用它的构造函数
        • 通过给 this.state 赋值对象来初始化内部 state
        • 为事件处理函数绑定实例
      • static getDerivedStateFromProps()
        • static getDerivedStateFromProps(props, state)
        • 此方法使用较少,无法获取this示例,在render()前调用
        • 在组件初始化和后续的更新过程中都会被调用
      • render()
        • 纯函数,执行渲染
        • 如果 shouldComponentUpdate() 返回 false,则不会调用 render()
      • componentDidMount()
        • 组件挂载后(插入 DOM 树中)立即调用
        • 获取网络数据
        • 添加订阅
    • 更新
      • static getDerivedStateFromProps()
        • static getDerivedStateFromProps(props, state)
        • 此方法使用较少,无法获取this示例,在render()前调用
        • 在组件初始化和后续的更新过程中都会被调用
      • shouldComponentUpdate()
        • shouldComponentUpdate(nextProps, nextState),返回Boolean值
        • 当 props 或 state 发生变化时,在执行渲染前调用。默认返回true
        • 作为性能优化的方式,但是尽量少用,去使用PureComponent组件替代
      • render()
        • 纯函数,执行渲染
        • 如果 shouldComponentUpdate() 返回 false,则不会调用 render()
      • getSnapshotBeforeUpdate()
        • getSnapshotBeforeUpdate(prevProps, prevState)
        • 此方法使用很少,在组件最近一次渲染前调用
        • 应返回 snapshot 的值(或 null),作为componentDidUpdate(prevProps, prevState, snapshot)的入参
        • 组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)
        • 回值将作为参数传递给 componentDidUpdate()
      • componentDidUpdate()
          componentDidUpdate(prevProps) {
              // 典型用法(不要忘记比较 props):
              if (this.props.userID !== prevProps.userID) {
                  this.fetchData(this.props.userID);
              }
           }
        
        • 更新后会被立即调用。首次渲染不会执行此方法
        • 组件更新后,可以进行DOM操作
        • 调用setState(),需要用条件语句包裹,否则死循环
    • 卸载
      • componentWillUnmount()
        • 组件卸载及销毁之前直接调用
        • 清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅
        • 不应调用 setState(),因为该组件将永远不会重新渲染

高级指南

  • Context
    • Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法
    • 通常将UI主题、用户信息等一些组件公用数据放到context中,作为组件的共享数据
    • 关键API
      • React.createContext
      • Context.Provider
      • Context.Consumer
  • Refs
    • Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素
    • 提供了非props的父组件和子组件交互方式,可以直接在父组件中修改子组件实例
    • 通过 .current去访问ref属性
    • class组件
      • React.createRef()
    • 函数式组件
      • 函数组件没有实例,不能直接使用Ref,可以通过forwardRef()
      • 内部使用 useRef()
    • ref转发的过程
      • 调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量
      • 指定 ref 为 JSX 属性,将其向下传递给 <FancyButton ref={ref}>
      • React 传递 ref 给 forwardRef 内函数 (props, ref) => ...,作为其第二个参数
      • 向下转发该 ref 参数到 <button ref={ref}>,将其指定为 JSX 属性
      • 当 ref 挂载完成,ref.current 将指向 <button> DOM 节点
  • 高阶组件(HOC)
    • 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧
    • 高阶组件是参数为组件,返回值为新组件的函数
    • 因为Ref不是组件的props,透传 Ref 需要通过 React.forwardRef()
  • diff算法
    • Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计
      • tree diff
        • React 通过 updateDepth 对 Virtual DOM 树进行层级控制
        • 只比较同一层级的节点,即同一层的所有子节点
    • 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构
      • component diff
    • 对于同一层级的一组子节点,它们可以通过唯一 id 进行区分
      • element diff
  • 虚拟DOM
  • Fiber
    • render/reconciliation,可以中断
      • fiber tree
      • workInProgress tree
      • 调度器(Scheduler)React Fiber 与浏览器的核心交互流程
        • 优先级
          • synchronous,与之前的Stack Reconciler操作一样,同步执行
            • 首屏(首次渲染)
          • task,在next tick之前执行
          • animation,下一帧之前执行
            • requestAnimationFrame
          • high,在不久的将来立即执行
            • requestIdleCallback
          • low,稍微延迟执行也没关系
            • requestIdleCallback
          • offscreen,下一次render时或scroll时才执行
            • requestIdleCallback
      • 生命周期
        • componentWillMount(已废弃)
        • componentWillReceiveProps(已废弃)
        • getDerivedStateFromProps
        • shouldComponentUpdate
        • componentWillUpdate (已废弃)
      • fiber 如何中断/断点恢复
        • 中断:检查当前正在处理的工作单元,保存当前成果(firstEffect, lastEffect),修改 tag 标记一下,迅速收尾并再开一个requestIdleCallback,下次有机会再做
        • 断点恢复:下次再处理到该工作单元时,看 tag 是被打断的任务,接着做未完成的部分或者重做
    • commit 批量更新差异点 (effect list),不能被打断
      • 生命周期
        • componentDidMount
        • componentDidUpdate
        • componentWillUnmount
  • 合成事件
    • 事件注册React 事件原理
      • document注册事件
      • 在组件挂载阶段,react 根据组件本身声明的事件类型(onclick、onchange、等等),通过 addEventListener 给 document 添加事件监听,然后指定统一的回调函数 dispatchEvent,同一事件不论注册几次,最终只会保留一个有效实例,从而减少内存开销。
      • 存储事件回调
      • React 会把组件内所有的事件统一存放到一个对象中(listenerBank),通过事件类型进行分类,回调函数的存储采用键值对(key/value)的方式,key 是组件的唯一标识 id,value 对应的就是事件的回调函数。
    • 事件分发
    • React 的事件触发只会发生在 DOM 事件流的冒泡阶段,因为在 document 上注册时就默认是在冒泡阶段被触发执行

Hook

  • 解决的问题
    • 组件之间的复用状态逻辑
    • 组件的复杂度高,难以拆分为小的颗粒
  • 常用的hook
    • useState常用的React Hook
    • useContext
      • 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值
    • useEffect
      • 执行一个带有副作用的函数
      • 在浏览器完成布局与绘制之后,在一个延迟事件中被调用,但是它总会在任何新的渲染前执行
      • 组件卸载的时候需要清除一些副作用,useEffect 函数只需返回一个清除函数即可
    • useLayoutEffect
      • 在所有的 DOM 布局完成之后同步调用 effect触发重新渲染。通常用来获取元素的位置,比如scroll的值
    • useCallback
    • useMemo
    • useRef
    • useReducer
      • 类似redux的reducer
    • useImperativeHandle
    • useDebugValue

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏

欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后