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 节点。
一句话概括如何选择 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 写样式那样可以支持语法高亮,样式自动补全等。所以要更加注意一些样式单词拼错的问题。