CLAYYA

乌贼馋辣鱼的博客

React

2024-11-25

React

1.什么是JSX?

JSX

2.元素和组件有什么区别?

元素是一种简单的对象,描述了您希望在屏幕上显示的内容,以 DOM 节点或其他组件的形式。元素可以包含其 props 中的其他元素。创建 React 元素的成本很低。一旦创建了元素,就不能对其进行修改。

React 元素的 JavaScript 表现如下:

<div id="login-btn">Login</div>

组件可以以多种不同方式声明。它可以是一个带有 render()​ 方法的类,也可以被定义为一个函数。无论哪种方式,它都需要 props 作为输入,并返回一个 JSX 树作为输出。

const Button = ({ handleLogin }) => (
  <div id={"login-btn"} onClick={handleLogin}>
    Login
  </div>
);

3.何时使用类组件而非函数组件?

使用函数组件:

  • 如果你不需要状态或生命周期方法,并且你的组件完全是呈现性的。
  • 为了简洁性、可读性和现代编程实践,特别是在使用 React Hooks 处理状态和副作用时。

使用类组件:

  • 如果你需要管理状态或使用生命周期方法。
  • 在需要向后兼容或与旧代码集成的场景中。

4.什么是纯组件?

纯净组件是那些在相同状态和属性下渲染相同输出的组件。在函数组件中,你可以通过在组件周围包裹 memoized React.memo() ​API 来实现这些纯净组件。这个 API 通过浅比较之前的属性和新的属性来防止不必要的重新渲染,因此对于性能优化非常有帮助。但同时,它不会将之前的状态与当前状态进行比较,因为当你再次设置相同的状态时,函数组件本身默认阻止了不必要的渲染。

5. state与props有什么区别?

都是普通JS对象,但是使用方法和特性不同

state 实体由组件自身管理,并可通过 setState()​ 函数进行更新。与属性不同,状态可以由组件修改,用于管理组件的内部状态。即,状态充当组件的内存。此外,状态的变化会触发组件及其子组件的重新渲染。仅使用状态,组件无法变得可重用。

另一方面, props (简称“属性”)由父组件传递给组件,且是 read-only ,意味着它们不能被组件本身修改。即,props 作为函数的参数。此外,props 可以用于配置组件的行为,并在组件之间传递数据。通过使用 props,组件变得可以重用。

6.HTML 和 React 事件处理之间的差异是什么?

  1. html事件名称为小写,react一般采用驼峰命名法

  2. 在 HTML 中,你可以返回 false 以阻止默认行为:

    <a
      href="#"
      onclick='console.log("The link was clicked."); return false;'
    />
    

    而在 React 中,你必须明确调用 preventDefault()​:

    function handleClick(event) {
      event.preventDefault();
      console.log("The link was clicked.");
    }
    
  3. 在 HTML 中,你需要通过追加 ()​来调用函数。而在 React 中,你不应该在函数名后追加 ()​ 。

7.合成事件是什么?

SyntheticEvent​ 是浏览器原生事件的跨浏览器包装器。它的 API 与浏览器的原生事件相同,包括 stopPropagation()​ 和 preventDefault()​ ,除了所有浏览器中的事件作用方式相同。可以直接通过 nativeEvent​ 属性从合成事件访问原生事件。

8."key" 属性是什么,以及在元素的数组中使用它的好处是什么?

是一种在遍历数组渲染数据时应包含的特殊属性。 key 属性帮助 React 识别哪些项目已更改、添加或移除。key是唯一的在兄弟姐妹中

9.什么是虚拟DOM?

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

10.VDOM是如何工作的?

  1. 每当基础数据发生变化时,虚拟 DOM 表示中整个 UI 都会重新渲染。

    image

  2. 比较,然后计算出之前 DOM 表示和新表示之间的差异。

    image

  3. 完成计算后,真正的 DOM 将仅更新已实际发生变化的部分。

    image

11.shadow DOM与VDOM

shadow DOM是一种浏览器技术,主要用于为 Web 组件中的变量和 CSS 划定作用域。

虚拟 DOM 是 JavaScript 库在浏览器 API 之上实现的概念。

12.什么是受控组件?

在后续用户输入的表单中控制输入元素的组件称为受控组件,即,每一次状态变更都将关联一个处理函数。这意味着,显示的数据始终与组件的状态保持同步。

有状态组件:有状态组件是指拥有自己的状态(state)的React组件。状态可以是任何类型的数据,不仅仅是表单数据。 有状态组件可以管理自己的状态,并且可以在组件的生命周期中根据需要更新状态。

13.什么是不受控制的组件?

不受控组件是那些在内部存储自身状态的组件,当你需要时,通过 ref 查询 DOM 以获取其当前值。这有点类似于传统的 HTML。

14.React 中的“提升状态”是什么?

当多个组件需要共享相同的变化数据时,建议将共享状态提升到它们最近的共同祖先组件中。这意味着,如果两个子组件从其父组件共享相同的数据,那么应将状态移动到父组件中,而不是在两个子组件中维护本地状态。

15. 什么是Reconciliation(协调)?

是指React更新用户界面的过程。应用的状态发生变化时,React通过比较当前的虚拟DOM(Virtual DOM)与更新后的虚拟DOM,来确定实际DOM需要进行哪些修改、添加或删除,以反映应用的最新状太。这个过程允许React以最小化不必要的DOM更新,确保了渲染性能的优化和流畅的用户体验。

Diffing算法:React使用一个高效的协调算法来比较旧的和新的虚拟DOM,并确定所需的变更。这个算法执行一个差异比较过程,识别出需要更新实际DOM的最小操作集

16.什么是懒惰函数?

懒惰函数:React.lazy​,用于实现代码分割(Code Splitting)和按需加载(Lazy Loading)组件。它允许你定义一个动态加载的组件,这个组件只有在需要的时候才会被加载,从而减少初始加载时间,优化首屏加载性能,提高应用性能。

使用 React.lazy​ 时,你需要提供一个函数作为参数,这个函数使用动态 import()​ 语法来异步加载组件。例如:

import { lazy } from 'react';
const SomeComponent = lazy(() => import('./SomeComponent'));

这里的 import()​ 函数返回一个 Promise 对象,当组件第一次被渲染时,会触发这个 Promise,加载组件代码。一旦 Promise 解析完成,React 会渲染解析值的.default​属性作为 React 组件。

React.lazy ​返回的是一个 React 组件,你可以像使用常规组件一样使用这个懒加载组件。但是,由于懒加载组件在加载过程中可能还没有完成加载,你需要使用 <Suspense>​ 组件来包裹懒加载的组件,并提供一个 fallback​ 属性,以指定在组件加载期间显示的加载指示器或占位内容:

import { Suspense } from 'react';
<Suspense fallback={<div>Loading...</div>}>
  <SomeComponent />
</Suspense>

在上述代码中,如果 SomeComponent 还没有加载完成,<Suspense>​ 会显示 fallback​ 属性中定义的内容。一旦 SomeComponent 加载完成,<Suspense>​ 会渲染 SomeComponent。

目前懒惰函数不支持命名导出。

17.为什么<Fragments>​或<>​比<div>​好?

  1. 片段(<>​)在创建额外的 DOM 节点方面稍快且占用内存较少。这仅在非常大且深度较大的树上真正有益
  2. 一些 CSS 机制,如 Flexbox 和 CSS Grid,具有特殊父子女关系,中间添加 div 会使保持所需的布局变得困难。
  3. DOM 检查器更加简洁。

18.无状态组件与状态组件

如果组件的行为与其状态无关,那么它就可以是一个无状态组件。你可以使用函数或类来创建无状态组件。但除非你的组件需要使用生命周期钩子,否则你应该选择函数组件。如果你决定使用函数组件,这里有很多好处;它们易于编写、理解和测试,运行稍快,并且可以完全避免使用 this 关键字。

如果组件的行为依赖于组件的状态,那么可以称之为状态化组件。这些状态化组件要么是带有 Hooks 的函数组件,要么是类组件。

19.如何在 React 中对 props 进行验证?

当应用程序处于开发模式时,React 会自动检查我们为组件设置的所有属性,以确保它们具有正确的类型。如果类型不正确,React 将在控制台中生成警告消息。在生产模式下由于性能影响而禁用,可强制属性通过 isRequired定义

预定义的属性类型集:

  • PropTypes.number
  • PropTypes.string
  • PropTypes.array
  • PropTypes.object
  • PropTypes.func
  • PropTypes.node
  • PropTypes.element
  • PropTypes.bool
  • PropTypes.symbol
  • PropTypes.any

下面是一段代码示例,展示isRequired​的用法:

import React from "react";
import PropTypes from "prop-types";

function User({ name, age }) {
  return (
    <>
      <h1>{`Welcome, ${name}`}</h1>
      <h2>{`Age, ${age}`}</h2>
    </>
  );
}

User.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number.isRequired,
};

20.react的限制

React 只是一个视图库,不是一个完整的框架。

将 React 集成到传统的 MVC 框架中需要一些额外的配置。

21.静态类型检查方法

react.props​可以,但是一些相对大型的代码,建议使用Flow或TypeScript这样的静态类型检查器,它们在编译时执行类型检查并提供自动完成功能。

22.react-dom 包的用途是什么?

react-dom 包提供了一组针对 DOM 的特定方法,这些方法可以在您的应用的顶级使用。这个模块的大部分组件并非使用此模块所必需。此包的一些方法包括:render()​、hydrate()​、unmountConponentAtNode()​、createPortal()

23.ReactDOMServer 是什么?

在传统的 Web 开发中,浏览器从服务器获取 HTML 文件后,再通过 JavaScript 去渲染页面中的交互部分(比如使用 React 构建的组件),这个过程是客户端渲染(Client-Side Rendering,CSR)。而服务器端渲染(Server-Side Rendering,SSR)则是在服务器端就把完整的 HTML 页面生成好,然后发送给浏览器,浏览器可以更快地展示出页面内容,提升首屏渲染速度以及对搜索引擎优化(SEO)也很有帮助,ReactDOMServer就是 React 实现服务器端渲染的关键所在,是 React 提供的一个服务器端渲染工具,它允许你在 Node.js 环境中将 React 组件渲染为字符串形式的 HTML。

以下是 ReactDOMServer 的一些关键特性和方法:

  1. renderToString()​:用于将 React 组件渲染成对应的 HTML 字符串。例如,假设有一个简单的 React 组件定义如下:

    import React from 'react';
    
    const HelloWorld = () => {
        return <div>Hello, World!</div>;
    };
    

    可以使用ReactDOMServer.renderToString在服务器端把这个组件渲染成 HTML 字符串:

    import React from 'react';
    import ReactDOMServer from 'react-dom/server';
    
    const HelloWorld = () => {
        return <div>Hello, World!</div>;
    };
    
    const htmlString = ReactDOMServer.renderToString(<HelloWorld />);
    console.log(htmlString);
    
    

    运行上述代码,会输出类似<div data-reactroot="">Hello, World!</div>​这样的 HTML 字符串,这个字符串就可以嵌入到服务器返回给客户端的 HTML 页面中合适的位置。

  2. renderToStaticMarkup()​:它和renderToString​类似,但不会添加额外的 React 相关的 DOM 属性(比如data-reactroot等),生成的 HTML 更加 “纯净”,适用于那些不需要在客户端再次 “激活” React 进行交互的场景,纯粹只是为了生成静态的 HTML 页面展示。例如对于上面的HelloWorld组件,使用renderToStaticMarkup​的示例代码如下:

    import React from 'react';
    import ReactDOMServer from 'react-dom/server';
    
    const HelloWorld = () => {
        return <div>Hello, World!</div>;
    };
    
    const staticMarkup = ReactDOMServer.renderToStaticMarkup(<HelloWorld />);
    console.log(staticMarkup);
    

    此时输出的就是单纯的<div>Hello, World!</div>​这样简洁的 HTML 标记。

24.React v16.0之后的版本为什么要删除和Will相关生命周期?

React v16.0之后,React团队引入了新的Fiber架构来重写React的核心算法。这个重写的目标是为了提高React的性能和可维护性,并为未来的功能增加提供更好的基础。

在Fiber架构中,React引入了一种新的调度器,可以更好地管理组件的更新和渲染。为了实现这种调度器,React需要对组件的更新进行更细粒度的控制,以便根据优先级和其他因素来安排组件的更新。

在这个新的架构中,React决定删除一些生命周期方法,例如 componentWillMount、componentWillUpdate 和 componentWillUnmount。这是因为在Fiber架构下,React可以更好地管理组件的更新,使得这些生命周期方法在大多数情况下是不必要的。

相反,React引入了新的生命周期方法,例如 getDerivedStateFromProps 和 getSnapshotBeforeUpdate,来提供更好的组件更新控制的机制。

总之,React删除和Will相关生命周期是为了适应新的Fiber架构,提高React的性能和可维护性,并为未来的功能增加提供更好的基础

25.如何在 React 中使用 innerHTML?

26.

27.

28.

29.

30.