乐趣区

关于前端:2023年前端面试真题之React篇

人的毕生,总是不免有浮沉。不会永远如旭日东升,也不会永远苦楚潦倒。重复地一浮一沉,对于一个人来说,正是磨难。因而,浮在下面的,不用自豪;沉在底下的,更用不着乐观。必须以率直、虚心的态度,乐观进取、向前迈进。——松下幸之助

大家好,我是江辰,在现在的互联网大环境下,想必大家都或多或少且有感触,塌实的社会之下,只有一直的放弃心性,能力感知不同的播种,互勉。

2023 年最新的面试题集锦,时刻做好筹备。

本文首发于微信公众号:家养程序猿江辰

欢送大家点赞,珍藏,关注

文章列表

  • 2023 年前端面试真题之 JS 篇
  • 2023 年前端面试真题之 CSS 篇
  • 2023 年前端面试真题之 HTML 篇
  • 2023 年前端面试真题之编码篇
  • 2023 年前端面试真题之 Vue 篇

什么时候应用状态管理器?

从我的项目的整体架构来看,要抉择适宜我的项目背景的极速。如果我的项目背景不适宜应用状态管理器,那就没有肯定的必要性去应用,比方微信小程序等,能够从以下几个维度来看

用户的应用形式简单

  • 不同身份的用户有不同的应用形式(比方普通用户和管理员)
  • 多个用户之间能够合作
  • 与服务器大量交互,或者应用了 WebSocket
  • View 要从多个起源获取数据

从组件角度看

  • 某个组件的状态,须要共享
  • 某个状态须要在任何中央都能够拿到
  • 一个组件须要扭转全局状态
  • 一个组件须要扭转另一个组件的状态

什么渲染劫持?

什么是渲染劫持,渲染劫持的概念是管制组件从另一个组件输入的能力,当然这个概念个别和 react 中的高阶组件(HOC)放在一起解释比拟有明了。

高阶组件能够在 render 函数中做十分多的操作,从而管制原组件的渲染输入,只有扭转了原组件的渲染,咱们都将它称之为一种渲染劫持。

实际上,在高阶组件中,组合渲染和条件渲染都是渲染劫持的一种,通过反向继承,不仅能够实现以上两点,还能够加强由原组件 render 函数产生的 React 元素。

理论的操作中通过操作 state、props 都能够实现渲染劫持

怎么实现 React 组件的国际化呢?

依赖于 i18next 的计划,对于宏大的业务我的项目有个很蛋疼的问题,那就是 json 文件的保护。每次产品迭代都须要减少新的配置,那么这份配置由谁来保护,怎么保护,都会有很多问题,而且如果你的我的项目要反对几十个国家的语言,那么这几十份文件又怎么保护。

所以当初大厂比拟罕用的计划是,应用 AST,每次开发完新版本,通过 AST 去扫描所有的代码,找出代码中的中文,以中文为 key,调用智能翻译服务,去帮我的项目主动生成 json 文件。这样,再也不须要人为去保护 json 文件,所有都依赖工具进行自动化。目前曾经有大厂开源,比方滴滴的 di18n,阿里的 kiwi

React 如何进行代码拆分?拆分的准则是什么?

我认为 react 的拆分前提是代码目录设计规范,模块定义标准,代码设计规范,合乎程序设计的个别准则,例如高内聚、低耦合等等。

在咱们的 react 我的项目中:

  • 在 api 层面咱们独自封装,对外裸露 http 申请的后果。
  • 数据层咱们应用的 mobx 封装解决异步申请和业务逻辑解决。
  • 试图层,尽量应用 mobx 层面的传递过去的数据,批改逻辑。
  • 动态类型的资源独自搁置
  • 公共组件、高阶组件、插件独自搁置
  • 工具类文件独自搁置

React 中在哪捕捉谬误?

官网例子:

class ErrorBoundary extends React.Component {constructor(props) {super(props);
    this.state = {hasError: false};
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可能显示降级后的 UI
    return {hasError: true};
  }

  componentDidCatch(error, errorInfo) {
    // 你同样能够将谬误日志上报给服务器
    logErrorToMyService(error, errorInfo);
  }

  render() {if (this.state.hasError) {
      // 你能够自定义降级后的 UI 并渲染
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

应用

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

然而谬误边界不会捕捉:

try{}catch(err){}
/// 异步代码(例如 setTimeout 或 requestAnimationFrame 回调函数)/// 服务端渲染
/// 它本身抛出来的谬误(并非它的子组件 )

为什么说 React 中的 props 是只读的?

保障 react 的单向数据流的设计模式,使状态更可预测。如果容许自组件批改,那么一个父组件将状态传递给好几个子组件,这几个子组件随便批改,就齐全不可预测,不晓得在什么中央批改了状态,所以咱们必须像纯函数一样爱护 props 不被批改

怎么应用 Hooks 获取服务端数据?

import React, {useState, useEffect} from 'react';
import axios from 'axios';
function App() {const [data, setData] = useState({hits: [] });
  useEffect(async () => {
    const result = await axios('https://api/url/to/data',);
    setData(result.data);
  });
  return (
    <ul>
      {data.hits.map(item => (<li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}
export default App;

应用 Hooks 要恪守哪些准则?

  1. 只在最顶层应用 Hook

不要在循环,条件或嵌套函数中调用 Hook,确保总是在你的 React 函数的最顶层调用他们。

  1. 只在 React 函数中调用 Hook

不要在一般的 JavaScript 函数中调用 Hook。你能够:

  • ✅ 在 React 的函数组件中调用 Hook
  • ✅ 在自定义 Hook 中调用其余 Hook

React Fiber 它的目标是解决什么问题?

React15 的 StackReconciler 计划因为递归不可中断问题,如果 Diff 工夫过长(JS 计算工夫),会造成页面 UI 的无响应(比方输入框)的体现,vdom 无奈利用到 dom 中。

为了解决这个问题,React16 实现了新的基于 requestIdleCallback 的调度器(因为 requestIdleCallback 兼容性和稳定性问题,本人实现了 polyfill),通过工作优先级的思维,在高优先级工作进入的时候,中断 reconciler

为了适配这种新的调度器,推出了 FiberReconciler,将原来的树形构造(vdom)转换成 Fiber 链表的模式(child/sibling/return),整个 Fiber 的遍历是基于循环而非递归,能够随时中断。

更加外围的是,基于 Fiber 的链表构造,对于后续(React 17 lane 架构)的异步渲染和(可能存在的)worker 计算都有十分好的利用根底

说出几点你认为的 React 最佳实际

参考官网

React 为什么要搞一个 Hooks?

官网答复:

动机

Hook 解决了咱们五年来编写和保护成千上万的组件时遇到的各种各样看起来不相干的问题。无论你正在学习 React,或每天应用,或者更愿尝试另一个和 React 有类似组件模型的框架,你都可能对这些问题似曾相识。

在组件之间复用状态逻辑很难

React 没有提供将可复用性行为“附加”到组件的路径(例如,把组件连贯到 store)。如果你应用过 React 一段时间,你兴许会相熟一些解决此类问题的计划,比方 render props 和 高阶组件。然而这类计划须要从新组织你的组件构造,这可能会很麻烦,使你的代码难以了解。如果你在 React DevTools 中察看过 React 利用,你会发现由 providers,consumers,高阶组件,render props 等其余形象层组成的组件会造成“嵌套天堂”。只管咱们能够在 DevTools 过滤掉它们,但这阐明了一个更深层次的问题:React 须要为共享状态逻辑提供更好的原生路径。

你能够应用 Hook 从组件中提取状态逻辑,使得这些逻辑能够独自测试并复用。Hook 使你在无需批改组件构造的状况下复用状态逻辑。这使得在组件间或社区内共享 Hook 变得更便捷。

简单组件变得难以了解

咱们常常保护一些组件,组件起初很简略,然而逐步会被状态逻辑和副作用充斥。每个生命周期经常蕴含一些不相干的逻辑。例如,组件经常在 componentDidMount 和 componentDidUpdate 中获取数据。然而,同一个 componentDidMount 中可能也蕴含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中革除。互相关联且须要对照批改的代码被进行了拆分,而齐全不相干的代码却在同一个办法中组合在一起。如此很容易产生 bug,并且导致逻辑不统一。

在少数状况下,不可能将组件拆分为更小的粒度,因为状态逻辑无处不在。这也给测试带来了肯定挑战。同时,这也是很多人将 React 与状态治理库联合应用的起因之一。然而,这往往会引入了很多抽象概念,须要你在不同的文件之间来回切换,使得复用变得更加艰难。

为了解决这个问题,Hook 将组件中互相关联的局部拆分成更小的函数(比方设置订阅或申请数据),而并非强制依照生命周期划分。你还能够应用 reducer 来治理组件的外部状态,使其更加可预测。

难以了解的 class

除了代码复用和代码治理会遇到困难外,咱们还发现 class 是学习 React 的一大屏障。你必须去了解 JavaScript 中 this 的工作形式,这与其余语言存在微小差别。还不能遗记绑定事件处理器。没有稳固的语法提案,这些代码十分冗余。大家能够很好地了解 props,state 和自顶向下的数据流,但对 class 却束手无策。即使在有教训的 React 开发者之间,对于函数组件与 class 组件的差别也存在一致,甚至还要辨别两种组件的应用场景。

另外,React 曾经公布五年了,咱们心愿它能在下一个五年也与时俱进。就像 Svelte,Angular,Glimmer 等其它的库展现的那样,组件预编译会带来微小的后劲。尤其是在它不局限于模板的时候。最近,咱们始终在应用 Prepack 来试验 component folding,也获得了初步成效。然而咱们发现应用 class 组件会无心中激励开发者应用一些让优化措施有效的计划。class 也给目前的工具带来了一些问题。例如,class 不能很好的压缩,并且会使热重载呈现不稳固的状况。因而,咱们想提供一个使代码更易于优化的 API。

为了解决这些问题,Hook 使你在非 class 的状况下能够应用更多的 React 个性。从概念上讲,React 组件始终更像是函数。而 Hook 则拥抱了函数,同时也没有就义 React 的精力准则。Hook 提供了问题的解决方案,无需学习简单的函数式或响应式编程技术

状态治理解决了什么问题?

专一 view 层

React 官网是这么简介的。JavaScript library for building user interfaces. 专一 view 层 的特点决定了它不是一个全能框架,相比 angular 这种全能框架,React 性能较简略,繁多。比如说没有前端路由,没有状态治理,没有一站式开发文档等。

f(state) = view

react 组件是依据 state(或者 props)去渲染页面的,相似于一个函数,输出 state,输入 view。不过这不是残缺意义上的 MDV(Model Driven View),没有齐备的 model 层。顺便提一句,感觉当初的组件化和 MDV 在前端开发中正炽热,大势所趋 …

state 自上而下流向、Props 只读

从咱们最开始写 React 开始,就理解这条特点了。state 流向是自组件从外到内,从上到下的,而且传递下来的 props 是只读的,如果你想更改 props,只能下层组件传下一个包装好的 setState 办法。不像 angular 有 ng-model, vue 有 v-model,提供了双向绑定的指令。React 中的约定就是这样,你可能感觉这很繁琐,不过 state 的流向却更清晰了,单向数据流在大型 spa 总是要讨好一些的。

这些特点决定了,React 自身是没有提供弱小的状态治理性能的,原生大略是三种形式。

函数式组件有没有生命周期?

它没有提供生命周期概念,不像 class 组件继承 React.component,能够让你应用生命周期以及特意强调相干概念

immutable 的原理是什么?

应用字典树长久化数据结构,更新时可优化对象生成逻辑,降低成本

怎么避免 HTML 被本义?

dangerouslySetInnerHTML

说说你是如何进步组件的渲染效率的

是什么

react 基于虚构 DOM 和高效 Diff 算法的完满配合,实现了对 DOM 最小粒度的更新,大多数状况下,React 对 DOM 的渲染效率足以咱们的业务日常

简单业务场景下,性能问题仍然会困扰咱们。此时须要采取一些措施来晋升运行性能,防止不必要的渲染则是业务中常见的优化伎俩之一

如何做

类组件:

  • 继承 PureComponent
  • 应用 shouldComponentUpdate 优化

函数组件:

  • memo 模仿 PureComponent
  • 应用 useMemo 缓存变量
  • 应用 useCallback 缓存函数
  • 循环增加 key, key 最好用数组项的惟一值,不举荐用 index

总结

在理论开发过程中,前端性能问题是一个必须思考的问题,随着业务的简单,遇到性能问题的概率也在增高

除此之外,倡议将页面进行更小的颗粒化,如果一个过大,当状态产生批改的时候,就会导致整个大组件的渲染,而对组件进行拆分后,粒度变小了,也可能缩小子组件不必要的渲染

说说对高阶组件(HOC)的了解?

高阶函数(Higher-order function),至多满足下列一个条件的函数

  • 承受一个或多个函数作为输出
  • 输入一个函数

在 React 中,高阶组件即承受一个或多个组件作为参数并且返回一个组件,实质也就是一个函数,并不是一个组件

const EnhancedComponent = highOrderComponent(WrappedComponent);

上述代码中,该函数承受一个组件 WrappedComponent 作为参数,返回加工过的新组件 EnhancedComponent

高阶组件的这种实现形式,实质上是一个装璜者设计模式

说说对 React refs 的了解?

Refs 在计算机中称为弹性文件系统(英语:Resilient File System,简称 ReFS)

React 中的 Refs 提供了一种形式,容许咱们拜访 DOM 节点或在 render 办法中创立的 React 元素

实质为 ReactDOM.render() 返回的组件实例,如果是渲染组件则返回的是组件实例,如果渲染 dom 则返回的是具体的 dom 节点

class

class MyComponent extends React.Component {constructor(props) {super(props);
    this.myRef = React.createRef();}
  render() {return <div ref="myref" />;}
}

hooks

function App(props) {const myref = useRef()
  return (
    <>
      <div ref={myref}></div>
    </>
  )
}
退出移动版