响应式系统与React笔记 | 青训营

62 阅读3分钟

组件

组件的两种写法

Class组件

  1. 继承+构造函数
  2. 利用this存放数据与函数
  3. 利用render()方法渲染和html

image.png

函数式组件

  1. 没有生命周期,继承与构造函数
  2. 借助Hook
  3. return Jsx

image.png

组件传值

父传子,props

image.png

React.cloneElement()可以克隆一个子节点,并给它附带一些属性,因此当遇到要给一系列标签都附带同一属性的时候,可以封装一个Wrapper利用map给每个子元素都附加属性

子传父

  1. 事件触发回调

  2. ref转发

image.png

  1. 父组件定义ref,并将ref传给子组件
  2. 子组件接受ref,并给它添加change,clear等方法,并转发给父组件
  3. 父组件调用子组件传来的方法

组件间共享信息 context & reducer

image.png

image.png

  1. 在store里,定义Reducer,接收state与action,通过判定action的不同type而返回不同内容,并创建公共状态容器
  2. 在app里接收userReducer函数,和store容器,再利用userReducer方法返回更新userReducer的方法,并将通过createContext()的方法传递context给子组件
  3. 子组件通过useContext接收

组件设计

  1. 接口定义

image.png

  1. 类名前缀统一

image.png

  1. 避免行内样式

image.png

  1. 避免在js中直接引入样式文件

image.png

5.组件样式按需加载

image.png

常见API

image.png

Hooks

hook规则&原理

  1. 只能在最顶层使用hook

image.png

如果在条件判定内使用hook,当该条件为否时,其内部的hook将不被执行,从而破坏了hook调用的顺序,使得state与useState的顺序混乱

  1. 只能在React函数中调用Hook

    • 在React函数组件中或自定义Hook中调用
    • 自定义Hook必须以use开头
    • Hook中的state是完全隔离的
function useUpdatedEffect(effect, deps) {
    const firstRender = useRef(true);

    useEffect(() => {
        if (firstRender.current) {
            firstRender.current = false;
        }
        else {
            return effect();
        }
    }, deps);
}
function Form() {
    //...
    useUpdatedEffect(function persistForm() {
    localStorage.setItem( 'formData', name);
    }, [name]) ;
    // ...
}
  1. 过期闭包

image.png

  • 无论通过setCount()将count增加到何值,useEffect中输出的始终是0

解决方法: 只要将useEffect的第二个参数,即依赖设为count,就不会出现闭包问题

hook API

image.png

  1. setState()传入一个初始值,返回一个状态和set该状态的函数,通过调用该函数可以实现状态修改

  2. useEffect()传入一个函数,和一个数组,数组是状态的数组,为依赖项,该函数在mount和依赖项被set的时候执行

    有"副作用"的函数,要传入useEffect执行,副作用代表除了计算,还要做其他的事,如网络请求,更新dom等

  • 不要在循环,条件,嵌套里面使用hook

用react开发web应用

image.png

  • 当子组件的props没有发生,无需进行新一次渲染

    1. useCallback():定义一个不会每次都被重新定义的函数
    2. useMemo: 不会每次都会重新计算的值

优化用户体验

加载中

  • lazy()&Suspense

使用React.lazy()包裹路由,Suspence展示等待加载过程渲染的内容

image.png

错误执行

  • ErrorBoundary

在代码执行错误的时候渲染降级ui

image.png

React的实现

image.png

React.createElement()第一个参数为标签名,第二个参数是其属性,第三个参数为其子元素

如何更新dom

image.png

每次发生更新,不会直接更新dom,而是会更新虚拟dom,而后执行diff算法,比较虚拟dom树和真实dom树的差异

image.png

每当一个组件发生改变,其都会递归的更新其所有子组件,重新渲染整个虚拟dom的子树,然后才更新dom, 这也是react所产生的性能问题

如何更高效的diff

image.png

状态管理库

要使两个关系相隔很远的组件共享一个状态,需要将状态放在根节点上,而太多的状态堆积在根节点上,会影响性能,因此利用状态管理库,可以将状态抽离到ui外部进行统一管理

image.png