1. class 组件与函数组件的区别
1. 语法不同
函数组件: 使用函数定义组件,通常是无状态的。在 React 16.8 之后,可以使用 Hook 来在函数组件中使用状态和其他 React 特性。
2. 状态的管理不同
3. 声明周期方法不同
类组件: 有一系列生命周期方法,如 componentDidMount、componentDidUpdate、componentWillUnmount 等,用于处理组件的生命周期事件。
const MyFunctionComponent = () => {
useEffect(() => {
// 在组件挂载后和更新后执行
return () => {
// 在组件卸载前执行
};
},
[] // 第二个参数来控制何时运行副作用函数
);
- 复杂性:
- 可读性和维护性:
总的来说,函数组件和 Hook 的方式更加推荐,特别是在新项目中。它们使得 React 组件更易于理解、编写和维护,同时提供了更灵活的状态管理和生命周期处理机制。类组件仍然存在,可能在老项目中或特殊场景中使用。
2. react 18 新特性有那些?
新增 createRoot API
自动批处理
React 18 通过默认做更多批量处理来增加开箱即用性能提升。批量处理指的是 React 为了提高性能将多个 state 更新分组到一个单独的重渲染。如果仍然希望setState之后立即重新渲染,只需要使用flushSync
包裹
function handleClick() {
// React 18 之前的版本
(/*...*/).then(() => {
setCount(c => c + 1); // 立刻重新渲染
setShow(show => !show); // 立刻重新渲染
});
}
function handleClick() {
// React 18
fecth(/*...*/).then(() => {
ReactDOM.flushSync(() => {
setCount(c => c + 1); // 立刻重新渲染
setFlag(f => !f);
})
})
}
过渡更新
用于并发渲染的并发新特性,开发者希望能够在Web Platform引入并发渲染,来实现多个渲染任务的并行渲染,其中Suspense就是基于此诞生的。
- startTransition() 在屏幕内容之间进行导航,而不会阻塞用户输入
- useDeferredValue() 节流处理开销巨大的重新渲染
- useTransition() startTransition的 hooks钩子
import { startTransition } from 'react';
// 紧急更新
setInputValue(input)
// 标记回调函数内的更新为 非紧急更新
startTransition(() => {
setSearchQuery(input)
})
这个hook适用于设置延迟值
function Page() {
const [filters, mergeFilter] = useMergeState(defaultFilters);
const deferedFilters = React.useDeferredValue(filters);
return (
<>
<Filters filters={filters} />
<List filters={deferedFilters}>
</>
)
}
useDeferredValue() 会将List组件的渲染变得更加平滑,深层次看来是 defered value 引起的渲染会被标记为不紧急渲染,会被filters引起的渲染进行抢占,进而达到用户快速输入搜索等场景下页面抖动或卡顿问题。
新的Hook
- useId 用于生成在客户端和服务端两侧都独一无二的 id
- useTransition 将一些状态更新标记为过渡更新
- useDeferredValue 允许推迟渲染树的非紧急更新,类似防抖
- useSyncExternalStore 允许使用第三方状态管理来支持并发模式,并且能通过对 store 进行强制更新实现数据同步。
- useInsertionEffect 允许 CSS-in-JS 库解决在渲染中注入样式的性能问题。
3. redux 和 react–redux 的区别
react–redux 是一个用于在 React 应用中管理状态(state)的库,它是基于 Redux 的 React 绑定库。Redux 是一种用于管理 JavaScript 应用程序状态的可预测状态容器,而 react–redux 则简化了在 React 应用中使用 Redux 的过程。
4. redux 中间件的原理
Redux 中间件是一种在 action 被发起和 reducer 处理这个 action 之间进行操作的机制。中间件允许你在 Redux 应用中的 dispatch 过程中拦截、检查、或者修改 action 和 state。Redux 中间件的原理涉及到 Redux 的 dispatch 过程、函数式编程的概念,以及中间件的链式调用。
Redux 中间件的原理主要体现在中间件链的设计和执行过程上:
-
中间件链的设计: 中间件被组织成一个链表形式,每个中间件都有机会处理 action。这个链表是通过 applyMiddleware 函数创建的。
-
dispatch 的增强: 中间件提供了一种方式,使得每个 action 发起的时候都可以执行一些额外的逻辑。中间件通过封装 dispatch 函数,并将其传递给链中的下一个中间件。
-
next 函数的传递: 在中间件链中,每个中间件都接收到一个 next 函数,它代表链中的下一个中间件。中间件可以选择调用 next(action) 来将 action 传递给下一个中间件,也可以选择不调用,中止链的执行。
-
异步处理: 由于中间件可以获取 dispatch 函数和 getState 函数,因此它们可以进行异步操作。例如,Redux Thunk 中间件就允许 action 创建函数返回一个函数而不仅仅是一个普通的 action 对象,这个函数可以在异步操作完成后再 dispatch。
整体来说,Redux 中间件的原理是通过改变 dispatch 函数的行为,使其能够在 action 到达 reducer 之前经过一系列的处理。这种机制使得 Redux 的功能能够被灵活地扩展和定制,例如通过中间件实现异步操作、日志记录、时间旅行调试等功能。
5. setState 发生了什么 ,render 函数做了什么
setState
render函数
setState触发了React的更新流程,而render函数则负责描述组件在更新后的状态应该如何呈现,并最终将这个描述应用到实际的DOM上。 React通过使用虚拟DOM和差异算法,尽可能高效地更新实际DOM,以提高性能和用户体验。
6. 虚拟DOM, Fiber
虚拟DOM
虚拟DOM是React的一种概念,它是在内存中维护的一份虚拟的DOM树。当组件的状态发生变化时,React首先在虚拟DOM上进行操作,而不是直接操作实际的DOM。这个虚拟DOM是一个轻量级的 JavaScript 对象树,它映射了真实DOM的结构。
组件状态更新: 当组件的状态发生变化时,React会创建一个新的虚拟DOM树。
虚拟DOM对比: 新的虚拟DOM树与先前的虚拟DOM树进行比较,找出发生变化的部分。
差异计算: React使用差异算法来计算需要进行更新的最小操作集。
实际DOM更新: 最终,React将计算出的变化应用到实际的DOM上,实现页面的更新。
通过使用虚拟DOM,React可以最小化直接操作实际DOM的次数,从而提高性能。这是因为直接DOM操作通常是昂贵的,而虚拟DOM的比较和计算过程是在内存中进行的,相对来说更快。
Fiber
Fiber是React 16 中引入的一种新的协调引擎,用于更灵活地控制React的渲染过程。在React 16之前,React的渲染过程是递归的,当组件层次很深时,可能导致浏览器阻塞。
Fiber的目标是实现增量式渲染,使React能够在多个帧中分割渲染工作,防止阻塞主线程。Fiber架构引入了一种新的数据结构,可以更灵活地中断、终止或恢复渲染过程,以适应不同的优先级和交互场景。
要点包括:
可中断的渲染: Fiber允许React在执行过程中中断渲染,执行其他高优先级的任务,然后返回并继续渲染。这有助于提高应用的响应性。
优先级调度: Fiber引入了任务调度器,可以根据任务的优先级动态调整渲染的顺序,确保高优先级任务优先完成。
总的来说,虚拟DOM和Fiber是React中两个关键的技术,它们共同为React提供了高效的渲染和更新机制,提高了应用的性能和用户体验。
7. useEffect 与 useLayoutEffect 的区别? 同步异步
useEffect:
useEffect(() => {
// 异步执行的副作用
console.log('useEffect callback');
}, [/* dependencies */]);
如何选择
如果你的副作用不需要同步执行,并且不影响布局,那么使用 useEffect
是更安全的选择,因为它不会导致阻塞。
如果你的副作用依赖于 DOM 的布局信息,并且需要在浏览器绘制之前立即执行,那么 useLayoutEffect
可能更适合。
大多数情况下,优先选择使用 useEffect,因为它更不容易导致性能问题。 useLayoutEffect 应该在确实需要在布局阶段同步执行的情况下使用。
8. useCallback 和 useMemo的区别
useCallback
和 useMemo
都是 React 中用于性能优化的 Hook,它们的目标是避免不必要的计算和渲染。尽管它们在使用上有相似之处,但它们的主要区别在于它们的应用场景和返回值的类型。
useCallback 用于缓存回调函数,以避免在每次渲染时创建新的回调。它的语法如下:
const memoizedCallback = useCallback(
() => {
// 回调函数
},
[/* 依赖项数组 */]
);
应用场景: 主要用于防止回调函数在每次渲染时都被重新创建,特别是在传递给子组件时,可以避免不必要的子组件重新渲染。
返回值: 返回一个 memoized(记忆的)版本的回调函数
。
useMemo
用于缓存计算结果,以避免在每次渲染时重新计算。它的语法如下:
const memoizedValue = useMemo(
() => {
// 计算结果
return computeExpensiveValue(a, b);
},
[a, b]
);
应用场景: 主要用于优化计算昂贵的值
,确保只在相关依赖项变化时进行重新计算。
返回值: 返回一个 memoized(记忆的)版本的计算结果
。
区别
返回类型: useCallback 返回一个 memoized 的回调函数,而 useMemo 返回一个 memoized 的计算结果。
主要应用场景: useCallback 主要用于缓存回调函数,而 useMemo 主要用于缓存计算结果。
总的来说,useCallback 用于缓存回调函数,而 useMemo 用于缓存计算结果。选择使用哪个取决于你的具体需求。如果你需要缓存一个回调函数以避免不必要的重新渲染,使用 useCallback。如果你需要缓存计算结果以提高性能,使用 useMemo。在一些情况下,你可能需要同时使用这两个 Hook。
9. Webpack 打包原理
Webpack 是一个现代的 JavaScript 应用程序静态模块打包工具。它的打包原理涉及以下关键概念:
入口(Entry): Webpack 从一个或多个入口点开始,根据入口点的依赖关系,递归地构建一个依赖图。
依赖图(Dependency Graph): Webpack 分析入口文件及其所有直接或间接依赖的文件,形成一个依赖图。每个模块都可以是一个文件,也可以是一个通过加载器(Loaders)处理的文件。
加载器(Loaders): 加载器是用于对模块进行转换的工具,它允许你在 import 模块时预处理文件。例如,可以使用 Babel 加载器将 ES6 代码转换为 ES5。
插件(Plugins): 插件用于执行各种任务,例如优化、压缩、拷贝文件等。插件可以在整个构建过程中执行各种任务,包括对生成的 bundle 进行优化和处理。
输出(Output): Webpack 根据依赖图生成一个或多个输出文件,这些文件包含了打包后的代码。输出文件的生成位置和文件名可以通过配置进行指定。
模块(Modules): 在 Webpack 中,一切皆模块。每个文件都被视为一个模块,并且可以包含 JavaScript、CSS、图片等各种类型的资源。
解析(Resolving): Webpack 从入口开始解析模块的依赖关系,找到每个模块的位置。
加载(Loading): 解析完成后,Webpack 将加载模块,这可能涉及到对文件的读取、转换和编译。
转换(Transformation): 加载器对模块进行转换,例如将 ES6 语法转换为 ES5、将 Sass 转换为 CSS 等。
打包(Bundling): 经过加载和转换后的模块被放置到一个或多个 bundle 中,这是由输出配置指定的。
输出(Output): Webpack 将 bundle 写入文件系统,生成最终的打包结果。
整个过程中,Webpack 通过使用各种配置选项、加载器和插件来灵活地处理不同类型的文件和任务,实现高度可定制的打包过程。Webpack 的灵活性和强大性使得它成为现代前端开发中的主流打包工具。
原文地址:https://blog.csdn.net/iChangebaobao/article/details/134698454
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_31902.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!