🌞Moon Will Know
🏝️

2022.10.21 面试记录

发现面试官的大部分问题来自:https://q.shanyue.tech/

useEffectuseLayoutEffect 的区别

  • 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的一种,它继承了纯函数的特点与优点。在 propsstate 不改变时不会重复渲染。

2. 生命周期:shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState):boolean; 这个生命周期用来决定组件是否需要重新渲染,如果返回 true 则说明组件需要重新渲染。

React.useCallback 的使用场景

  • React.memo 配合使用,优化组件。
  • 作为依赖项时,避免高昂的计算和不必要的重复渲染。

React.useState 同步 or 异步,怎么马上获取更新后的值

同步还是异步

在 react17 中,setStateReact.useState 并不能保证是同步的,在生命周期函数和合成事件中是异步的,在原生事件监听器和 setTimeout 中是同步的。在 react18 中,是批量异步执行的。
拓展:合成事件
  1. 提供统一的 API,抹平各大浏览器差异
  1. 所有事件绑定在 React Root Element 进行事件委托

怎么马上获取值

  1. 使用 useRef 进行缓存
  1. 使用 自定义 hook 包装回调,类似 setSate

React 中共享全局方法的方式

  1. 使用 context
  1. 在路由嵌套时可以使用 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 中怎么做优化

  1. 使用 React.memoReact.useCallback 防止组件重复渲染。
  1. 使用 React.useMemoReact.useCallback 缓存比较耗性能的复杂计算。
  1. 使用 React.lazyimport() 进行组件懒加载和分包。
  1. 优化加载,多做缓存如 SWR。
  1. 将耗费性能的运算放在 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> 的值。
  • 关键字noneautoinitial.

双值写法

第一个值必须为一个无单位数,并且它会被当作 <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 变为可选

使用联合类型

Dapp 唤起浏览器钱包