2022年React面试题

1. 什么是虚拟DOM

虚拟 DOM (VDOM)是真实 DOM 在内存中的表示。UI 的表示形式保存在内存中,并与实际的 DOM 同步。这是一个发生在渲染函数被调用和元素在屏幕上显示之间的步骤,整个过程被称为调和。

2. 类组件和函数组件之间的区别是啥?

  • 类组件可以使用其他特性,如状态state和生命周期钩子。
  • 当组件只是接收props渲染到页面时,就是无状态组件,就属于函数组件,也被称为哑组件或展示组件。

函数组件和类组件当然是有区别的,而且函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。

区别 函数组件 类组件
是否有 没有
是否有生命周期 没有
是否有状态 没有

3. React 中 refs 干嘛用的?

refs提供了一种访问在render方法中创建的 DOM 节点或者 React 元素的方法。在典型的数据流中,props是父子组件交互的唯一方式,想要修改子组件,需要使用新的props重新渲染它。凡事有例外,某些情况下咱们需要在典型数据流外,强制修改子代,这个时候可以使用Refs

4. React 组件生命周期有哪些不同阶段?

  • componentWillMount :在渲染之前执行,用于根组件中的 App 级配置。
  • componentDidMount:在第一次渲染之后执行,可以在这里做AJAX请求,DOM 的操作或状态更新以及设置事件监听器。
  • componentWillReceiveProps:在初始化render的时候不会执行,它会在组件接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染
  • shouldComponentUpdate:确定是否更新组件。默认情况下,它返回true。如果确定在 stateprops更新后组件不需要在重新渲染,则可以返回false,这是一个提高性能的方法。
  • componentWillUpdate:在shouldComponentUpdate返回 true 确定要更新组件之前件之前执行。
  • componentDidUpdate:它主要用于更新DOM以响应porpsstate更改。
  • componentWillUnmount:它用于取消任何的网络请求,或删除与组件关联的所有事件监听器。

5. React 常用的hook

useState \ useEffect\ useContext \ useReducer \ useCallback \ useImperativeHandle \ useMemo \ useRef

6. React 组件间有那些通信方式?

  • 父组件向子组件通信
    • 通过 props 传递
  • 子组件向父组件通信
    • 主动调用通过 props 传过来的方法,并将想要传递的信息,作为参数,传递到父组件的作用域中
  • 跨层级通信
    1. 使用 react 自带的 Context 进行通信,createContext 创建上下文, useContext 使用上下文。
      参考下面代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      import React, { createContext, useContext } from 'react';
      const themes = {
      light: {
      foreground: "#000000",
      background: "#eeeeee"
      },
      dark: {
      foreground: "#ffffff",
      background: "#222222"
      }
      };

      const ThemeContext = createContext(themes.light);

      function App() {
      return (
      <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
      </ThemeContext.Provider>
      );
      }

      function Toolbar() {
      return (
      <div>
      <ThemedButton />
      </div>
      );
      }

      function ThemedButton() {
      const theme = useContext(ThemeContext);
      return (
      <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
      </button>
      );
      }

      export default App;
    2. 使用 Redux 或者 Mobx 等状态管理库
    3. 使用订阅发布模式

7. 为什么 React 元素有一个 $$typeof 属性?

目的是为了防止 XSS 攻击。因为 Synbol 无法被序列化,所以 React 可以通过有没有 $$typeof 属性来断出当前的 element 对象是从数据库来的还是自己生成的。
如果没有 $$typeof 这个属性,react 会拒绝处理该元素。
相关阅读:为什么React元素有一个$$typeof属性?

8. 为什么 JSX 中的组件名要以大写字母开头?

因为 React 要知道当前渲染的是组件还是 HTML 元素。

9. redux 是什么?

Redux 是一个为 JavaScript 应用设计的,可预测的状态容器。

  • 它解决了如下问题:
    • 跨层级组件之间的数据传递变得很容易
    • 所有对状态的改变都需要 dispatch,使得整个数据的改变可追踪,方便排查问题。
  • 但是它也有缺点:
    • 概念偏多,理解起来不容易
    • 样板代码太多

10. setState到底是异步还是同步?

先给出答案: 有时表现出异步,有时表现出同步

  • setState只在合成事件和钩子函数中是“异步”的,在原生事件和setTimeout 中都是同步的
  • setState 的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的“异步”,当然可以通过第二个参数setState(partialState, callback)中的callback拿到更新后的结果
  • setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次setStatesetState的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时setState多个不同的值,在更新时会对其进行合并批量更新

11.什么是跨域?如何解决跨域问题?

浏览器对于javascript的同源策略的限制。

  1. 域名不同 www.jd.comwww.taobao.com
  2. 端口不同 www.jd.com:8080www.jd.com:8081
  3. 二级域名不同 item.jd.com 与 miaosha.jd.com
  4. http和https也属于跨域

解决跨域问题的方案

  1. Jsonp
    最早的解决方案,利用script标签可以跨域的原理实现。
    限制
    需要服务的支持
    只能发起GET请求
  2. nginx反向代理
    思路是:利用nginx把跨域反向代理为不跨域,支持各种请求方式
    缺点:需要在nginx进行额外配置,语义不清晰
  3. CORS
    规范化的跨域请求解决方案,安全可靠。
    优势
    在服务端进行控制是否允许跨域,可自定义规则
    支持各种请求方式
    缺点
    会产生额外的请求
    如果服务器允许跨域,需要在返回的响应头中携带下面信息:
    1
    2
    3
    Access-Control-Allow-Origin: http://manage.handou.com
    Access-Control-Allow-Credentials: true
    Content-Type: text/html; charset=utf-8
    Access-Control-Allow-Origin:允许哪个域名进行跨域,是一个具体域名或者*(代表任意域名)
    Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

要想操作cookie,需要满足3个条件:
服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
浏览器发起ajax需要指定withCredentials 为true
响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名