type
status
date
slug
summary
tags
category
icon
password
虚拟DOM
虚拟DOM是什么?
- 在传统的Web应用中,数据的变化会实时地更新到用户界面中,于是每次数据微小的变化都会引起DOM的渲染。
- 虚拟DOM是将所有的操作聚集到一块,计算出所有的变化后,统一更新一次虚拟DOM。
虚拟DOM作用
- 提高开发效率,只需要关注业务代码。无需关注DOM更新,React会将这一切计算好。
- 虚拟DOM感受到变化的时候,只会更新局部,而非整体。同时,虚拟DOM会减少了非常多的DOM操作 ,所以性能会提升很多
React Diff算法
- Tree Diff:认为跨层级移动节点操作比较少,只比较同一层级的节点。
- Component Diff:组件类型不一样,React就认为不是同一个组件。
- Element diff:同一层级的子节点,比较唯一Key。有三类操作:插入,移动,删除。
React Hook原理
Fiber结构
- parent:指向父级Fiber节点:
- child:指向子Fiber节点
- sibling:指向右边的兄弟节点

为什么要用Fiber
- 在 react16 引入 Fiber 架构之前,react 会采用递归方法对比两颗虚拟DOM树,找出需要改动的节点,然后同步更新它们,这个过程 react 称为reconcilation(协调)。在reconcilation期间,react 会同步执行操作,提交到真实 DOM 的更改,会一直占着浏览器的资源,不能中断,中断后就不能恢复,使得我们一些用户操作定时器等等事件无法得到响应,是一个非常糟糕的用户体验。
怎么实现的
- 一个节点就是一个Fiber任务,在浏览器的requestIdleCallback回调中,判断空余时间执行Fiber任务。
Hooks原理
- hooks 实现是基于 fiber 的,通常链表形式串起来。每次会执行链表中的Hooks更新,所以不能用在条件和循环语句中。
- 每个 fiber 节点的 memoizedState 保存了对应的数据,不同的 hooks 通过使用该对应数据完成对应的逻辑功能。
常见Hooks状态
- useState/useReducer:memoizedState 等于 state 的值
- useEffect:memoizedState 保存的是 effect 链表(包含 useEffect 第一个参数回调与第二个参数依赖项数组的值)
- useRef:memoizedState 等于 { current: 当前值 }
- useCallback:保存两个参数值,memoizedState 等于 [callback, deps],缓存的是函数
- useMemo:保存两个参数值,memoizedState 等于 [callback(), deps],缓存的是函数执行计算结果。
重排和重绘
- 解析HTML:浏览器将HTML解析成DOM树。
- 解析CSS:浏览器将CSS解析成CSSOM树。
- 构建渲染树:浏览器将DOM树和CSSOM树结合,生成渲染树。
- 布局(Layout):浏览器根据渲染树计算每个节点的几何信息(位置和大小)。
- 绘制(Paint):浏览器将渲染树的每个节点绘制到屏幕上。
其中Layout就是重排,Paint就是重绘

组件间传值
- 父向子传值:props传值
- 子向调用父方法:props传入回调函数
- 父调用子方法:父组件useRef拿到子组件ref,子组件在useImperativeHandle中声明暴露给父组件的方法。
- 父跨层级向子传值:
- Redux
- Provider,userContext
- EventBus,数据流转会变得不可控,建议用在小项目上。
自己基于Provider实现Redux
- provider传参dispatch和state
- useContext获取state和dispatch,state数据发生变化时刷新视图
- dispatch根据action改变state的值
性能优化
- 网络优化
- 开启gzip
- 使用webp图片
- 开启Tree Shaking,移除未使用JS代码。使用MiniCssExtractPlugin进行CSS压缩。
- 协商缓存,强缓存
- 静态资源CDN
- 渲染优化
- 减少重排重绘
- 虚拟列表优化
- 代码分割和懒加载
- useMemo,memo缓存组件
- 节流和防抖
- 进阶优化
- 预加载回包
- SSR云端预加载回包
媒体适配
CSS中使用@media根据设备的宽高映射不同的样式
JSBridge原理
JSbridge用于JS和Native之间互相通信,方便数据传输和回调方法
JS调用JAVA:WebView.addJavascriptInterface()将对象注册到JavaScript,这个对象中@JavascriptInterface 注解标记的方法,会被暴露给 JS,使得 JS 可以直接调用这些方法。
JAVA调用JS:WebView.evaluateJavascript(),前端注册回调window.jsBridge.receiveNativeMessage
Webpack插件
loader:是个转换函数,输入文件输出处理过的文件。如babel,ts-loader
plugin:插件,基于Webpack的生命周期做些扩展操作。
TerserPlugin:压缩JS
cssnano:减少CSS体积
SplitChunksPlugin:切分代码块
- 用正则匹配三方包名,将共用的三方库打包如vender。chunks=”inital”
- 非首屏入口,使用懒加载import()。chunks=”all”|”async”