React 进阶实践指南 的学习笔记

100 阅读4分钟

JSX

JSX 转化为 React createElement

jsx元素类型react.createElement 转换后type 属性
element元素类型react element类型标签字符串,例如 div
fragment类型react element类型symbol react.fragment类型
文本类型直接字符串
数组类型返回数组结构,里面元素被react.createElement转换
组件类型react element类型组件类或者组件函数本身
三元运算 / 表达式先执行三元运算,然后按照上述规则处理看三元运算返回结果
函数执行先执行函数,然后按照上述规则处理看函数执行返回结果

React 针对不同 React element 对象会产生不同 tag (种类) 的fiber 对象。 对应关系如下:

export const FunctionComponent = 0;       // 函数组件
export const ClassComponent = 1;          // 类组件
export const IndeterminateComponent = 2;  // 初始化的时候不知道是函数组件还是类组件 
export const HostRoot = 3;                // Root Fiber 可以理解为根元素 , 通过reactDom.render()产生的根元素
export const HostPortal = 4;              // 对应  ReactDOM.createPortal 产生的 Portal 
export const HostComponent = 5;           // dom 元素 比如 <div>
export const HostText = 6;                // 文本节点
export const Fragment = 7;                // 对应 <React.Fragment> 
export const Mode = 8;                    // 对应 <React.StrictMode>   
export const ContextConsumer = 9;         // 对应 <Context.Consumer>
export const ContextProvider = 10;        // 对应 <Context.Provider>
export const ForwardRef = 11;             // 对应 React.ForwardRef
export const Profiler = 12;               // 对应 <Profiler/ >
export const SuspenseComponent = 13;      // 对应 <Suspense>
export const MemoComponent = 14;          // 对应 React.memo 返回的组件

Babel 解析 JSX 流程

JSX 语法实现来源于这两个 babel 插件:

@babel/plugin-syntax-jsx : 使用这个插件,能够让 Babel 有效的解析 JSX 语法。
@babel/plugin-transform-react-jsx :这个插件内部调用了 @babel/plugin-syntax-jsx,可以把 React JSX 转化成 JS 能够识别的 createElement 格式。

组件

组件通信:

  • props 和 callback 方式
  • ref 方式。
  • React-redux 或 React-mobx 状态管理方式。
  • context 上下文方式。
  • event bus 事件总线。

State

批量更新: batchUpdate

详细的

React 同一级别更新优先级关系是:

flushSync 中的 setState > 正常执行上下文中 setState > setTimeout ,Promise 中的 setState。

异同

类组件中的 setState 和函数组件中的 useState 有什么异同?
相同点:

  • 首先从原理角度出发,setState和 useState 更新视图,底层都调用了 scheduleUpdateOnFiber 方法,而且事件驱动情况下都有批量更新规则。

不同点:

  • 在不是 pureComponent 组件模式下, setState 不会浅比较两次 state 的值,只要调用 setState,在没有其他优化手段的前提下,就会执行更新。但是 useState 中的 dispatchAction 会默认比较两次 state 是否相同,然后决定是否更新组件。
  • setState 有专门监听 state 变化的回调函数 callback,可以获取最新state;但是在函数组件中,只能通过 useEffect 来执行 state 变化引起的副作用。
  • setState 在底层处理逻辑上主要是和老 state 进行合并处理,而 useState 更倾向于重新赋值。

props

props 可以是什么?

  • props 作为一个子组件渲染数据源。
  • props 作为一个通知父组件的回调函数。
  • props 作为一个单纯的组件传递。
  • props 作为渲染函数。
  • render props,与上一条的的区别是放在了 children 属性上。
  • render component 插槽组件。

生命周期

在讲 React 生命周期之前,有必要先来简单聊聊 React 两个重要阶段,render 阶段和 commit 阶段,React 在调和( render )阶段会深度遍历 React fiber 树,目的就是发现不同( diff ),不同的地方就是接下来需要更新的地方,对于变化的组件,就会执行 render 函数。在一次调和过程完毕之后,就到了commit 阶段,commit 阶段会创建修改真实的 DOM 节点。

image.png

一句话概括如何选择 useEffect 和 useLayoutEffect :修改 DOM ,改变布局就用 useLayoutEffect ,其他情况就用 useEffect 。

Ref

好好看这个

Context

context解决了:

  • 解决了 props 需要每一层都手动添加 props 的缺陷。
  • 解决了改变 value ,组件全部重新渲染的缺陷。

react-redux 就是通过 Provider 模式把 redux 中的 store 注入到组件中的。

CSS

CSS Modules 优点:

  • CSS Modules 的类名都有自己的私有域的,可以避免类名重复/覆盖,全局污染问题。
  • 引入 css 更加灵活,css 模块之间可以互相组合。
  • class 类名生成规则配置灵活,方便压缩 class 名。

CSS Modules 的注意事项:

  • 仅用 class 类名定义 css ,不使用其他选择器。
  • 不要嵌套 css .a{ .b{} } 或者重叠 css .a .b {} 。

CSS IN JS 特点

  • CSS IN JS 本质上放弃了 css ,变成了 css in line 形式,所以根本上解决了全局污染,样式混乱等问题。
  • 运用起来灵活,可以运用 js 特性,更灵活地实现样式继承,动态添加样式等场景。
  • 由于编译器对 js 模块化支持度更高,使得可以在项目中更快地找到 style.js 样式文件,以及快捷引入文件中的样式常量。
  • 无须 webpack 额外配置 css,less 等文件类型。

CSS IN JS 注意事项

  • 虽然运用灵活,但是写样式不如 css 灵活,由于样式用 js 写,所以无法像 css 写样式那样可以支持语法高亮,样式自动补全等。所以要更加注意一些样式单词拼错的问题。

高阶组件

快看这个,讲的好