发现面试官的大部分问题来自:https://q.shanyue.tech/
useEffect 和 useLayoutEffect 的区别
useEffect是异步执行的,执行时机是浏览器渲染完成之后。
useLayoutEffect是同步执行的,会阻塞浏览器渲染,执行时机是浏览器渲染完成之后,和componentDidMount等价。有关于DOM的操作最好放到useLayoutEffect中去。
拓展:React 生命周期,React 内置钩子。
React.memo 的用途
React.memo(component[, areEqual]) React.memo 是一个高阶组件,将组件通过 React.memo包装时将会在相同 props 的情况下跳过渲染组件的操作并直接复用最近一次渲染的结果。默认情况下其只会对复杂对象做浅层对比,也可以通过第二个比对函数来进行控制是否更新。
还有什么方法可以实现这个功能
1. 类组件:React.PureComponent
Pure Components是React Component的一种,它继承了纯函数的特点与优点。在
props 与state 不改变时不会重复渲染。2. 生命周期:shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState):boolean; 这个生命周期用来决定组件是否需要重新渲染,如果返回 true 则说明组件需要重新渲染。React.useCallback 的使用场景
- 和
React.memo配合使用,优化组件。
- 作为依赖项时,避免高昂的计算和不必要的重复渲染。
React.useState 同步 or 异步,怎么马上获取更新后的值
同步还是异步
在 react17 中,
setState 和 React.useState 并不能保证是同步的,在生命周期函数和合成事件中是异步的,在原生事件监听器和 setTimeout 中是同步的。在 react18 中,是批量异步执行的。拓展:合成事件
- 提供统一的 API,抹平各大浏览器差异
- 所有事件绑定在 React Root Element 进行事件委托
怎么马上获取值
- 使用
useRef进行缓存
- 使用 自定义 hook 包装回调,类似
setSate
React 中共享全局方法的方式
- 使用 context
- 在路由嵌套时可以使用 outlet,但本质还是 context
HOC
高阶组件是参数为组件,返回值为新组件的函数,是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
高阶组件是组件的包装器,可以为组件注入额外的 props,或拓展组件的生命周期。大多数 HOC 的功能可以使用 自定义 hooks 替代,但 HOC 不用在组件中重复调用,写法有时比较简单。
keep-alive 的实现
keep-alive 是一个抽象组件,它缓存了第一个子元素的 vnode,并为子组件和最近一个非抽象祖先元素建立父子关系。keep-alive 缓存组件名到 this.keys 中,缓存组件到 this.caches 中。在加载组件时分为首次加载和缓存加载,首次加载时会缓存了
vnode创建生成 DOM 节点,首次渲染时会正常执行生命周期。在缓存加载时,只是更新子组件为缓存组件。
在 React 中怎么缓存路由
使用 react-activation ,用法和
keep-alive 相似。实现原理:由于 React 会卸载掉处于固有组件层级内的组件,所以我们需要将 <KeepAlive> 中的组件,也就是其 children 属性抽取出来,渲染到一个不会被卸载的组件 <Keeper> 内,再使用 DOM 操作将 <Keeper> 内的真实内容移入对应 <KeepAlive>,就可以实现此功能。
React 路由拦截
React-router 中存在 loader 函数,这个函数会在路由渲染前被调用。类似于 vue-router 中的单路由导航守卫,可以在这个函数内进行权限校验和跳转。拓展 :loader 函数的返回结果可以通过useLoaderData来获取。
React 中怎么做优化
- 使用
React.memo和React.useCallback防止组件重复渲染。
- 使用
React.useMemo或React.useCallback缓存比较耗性能的复杂计算。
- 使用
React.lazy和import()进行组件懒加载和分包。
- 优化加载,多做缓存如 SWR。
- 将耗费性能的运算放在 worker 线程或者使用 wasm。
Axios 和 fetch 的区别
Axios 是对 XHR 的封装库,内部实现了对请求的拦截处理。
XHR 可以获取到上传的进度。
fetch 是浏览器的原生 API,不需要额外引入库,如果要支持 PWA,就必须使用 fetch。
fetch 可以获取到下载的进度。
fetch 可以在 worker 中被监听并缓存。
Function.prototype.call 的函数签名
拓展:applay([thisArg,argArr])bind(thisArg [, arg1, /* …, */ argN])函数签名:一个函数签名定义了函数或方法的输入与输出。
flex 属性
flex-grow
flex 主尺寸的增长系数,flex 容器中分配剩余空间的相对比例。剩余空间是 flex 容器的大小减去所有 flex 项的大小加起来的大小。
flex-shrink
空间不够时的压缩比例,默认值为 1,设置为 0 表示不压缩。
flex-basis
表示被分配到的空间,类似于宽度,但比宽度优先。
单值写法
- 一个无单位数 : 它会被当作
flex:<number> 1 0;<flex-shrink>的值被假定为 1,然后<flex-basis>的值被假定为0。
- 一个有效的 宽度 值:它会被当作
<flex-basis>的值。
- 关键字
none,auto或initial.
双值写法
第一个值必须为一个无单位数,并且它会被当作
<flex-grow> 的值。第二个值必须为以下之一:- 一个无单位数:它会被当作
<flex-shrink>的值。
- 一个有效的宽度值:它会被当作
<flex-basis>的值。
三值写法
- 第一个值必须为一个无单位数,并且它会被当作
<flex-grow>的值。
- 第二个值必须为一个无单位数,并且它会被当作
<flex-shrink>的值。
- 第三个值必须为一个有效的宽度值,并且它会被当作
<flex-basis>的值。
flex: auto; 等效于 flex: 1 1 auto;flex: initial; 等效于 flex: 0 1 auto;flex: none; 等效于 flex: 0 0 auto;Typescript 中如何使用元组作为type的 key
const 断言会将对象或数组定义为常量,arr 会被定义为只读元组。
先使用 typeof 获取只读元组的的类型,然后再使用 [number] 或 [any] 提取联合类型。
拓展:将对象转为联合类型
Typescript 如何让属性 a 的值/类型改变时,属性 b 变为可选
使用联合类型
