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 事件处理之间的差异是什么?
-
html事件名称为小写,react一般采用驼峰命名法
-
在 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."); }
-
在 HTML 中,你需要通过追加
()
来调用函数。而在 React 中,你不应该在函数名后追加()
。
7.合成事件是什么?
SyntheticEvent
是浏览器原生事件的跨浏览器包装器。它的 API 与浏览器的原生事件相同,包括 stopPropagation()
和 preventDefault()
,除了所有浏览器中的事件作用方式相同。可以直接通过 nativeEvent
属性从合成事件访问原生事件。
8."key" 属性是什么,以及在元素的数组中使用它的好处是什么?
是一种在遍历数组渲染数据时应包含的特殊属性。 key 属性帮助 React 识别哪些项目已更改、添加或移除。key是唯一的在兄弟姐妹中
9.什么是虚拟DOM?
虚拟 DOM(VDOM)是内存中对真实 DOM 的表示。UI 的表示保持在内存中,并与“真实”的 DOM 同步。这是在渲染函数被调用和屏幕上的元素显示之间发生的一步。整个过程称为重聚。
10.VDOM是如何工作的?
-
每当基础数据发生变化时,虚拟 DOM 表示中整个 UI 都会重新渲染。
-
比较,然后计算出之前 DOM 表示和新表示之间的差异。
-
完成计算后,真正的 DOM 将仅更新已实际发生变化的部分。
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>
好?
- 片段(
<>
)在创建额外的 DOM 节点方面稍快且占用内存较少。这仅在非常大且深度较大的树上真正有益 - 一些 CSS 机制,如 Flexbox 和 CSS Grid,具有特殊父子女关系,中间添加 div 会使保持所需的布局变得困难。
- 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 的一些关键特性和方法:
-
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 页面中合适的位置。 -
-
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.