React进阶面试题目(三)
如何在 React 中实现滚动动画?
在 React 中实现滚动动画可以通过多种方式实现,以下是一个基本的实现步骤:
- 构建组件:首先构建需要展示滚动动画的组件,例如一个 About 组件,它包含一些文本或元素。
- 监听滚动事件:在组件挂载后,通过 window.onscroll 事件监听滚动事件。
- 更新状态:根据滚动位置更新组件的状态,例如通过判断 document.documentElement.scrollTop 的值来决定是否显示滚动动画。
- 应用 CSS 动画:使用 CSS 动画或过渡效果来实现滚动动画。例如,可以定义一个 CSS 类来设置动画效果,并在状态更新时将其应用到元素上。
React Router 的路由是什么?它和普通路由有什么区别?有什么优缺点?
React Router 的路由是指在 React 应用中用于定义导航结构和处理 URL 变化的机制。与普通路由(通常指后端路由)相比,React Router 的路由是在前端实现的,它不会触发页面的重新加载,而是通过更改 DOM 结构来更新视图。
区别:
- 实现方式:React Router 的路由是在前端通过 JavaScript 实现的,而普通路由是在后端通过服务器实现的。
- 页面刷新:React Router 的路由切换不会刷新页面,而普通路由切换通常会刷新页面。
- 应用场景:React Router 主要用于单页应用(SPA),而普通路由则用于多页应用或传统的 Web 应用。
优缺点:
-
优点:
- 用户体验好:无需页面刷新即可切换视图,提高了用户体验。
- 易于维护:前端路由与视图组件紧密结合,使得应用的导航结构和视图逻辑更加清晰。
- 支持嵌套路由和参数化路由:可以方便地实现复杂的导航结构和动态内容展示。
-
缺点:
- 初次加载时间长:由于单页应用需要在前端加载整个应用的代码和资源,因此初次加载时间可能较长。
- 对 SEO 不太友好:由于前端路由不会触发页面的重新加载,搜索引擎可能无法很好地抓取和索引应用的页面。
在 React 项目中,如何应用 TypeScript?
在 React 项目中应用 TypeScript 可以提高代码的可读性和可维护性,同时提供类型检查和智能提示等功能。以下是应用 TypeScript 的步骤:
-
项目初始化:
- 使用
create-react-app
创建 TypeScript 项目:npx create-react-app my-app --template typescript
。 - 在现有项目中添加 TypeScript:安装 TypeScript 和类型声明文件,添加
tsconfig.json
文件,并将.js
文件重命名为.tsx
(如果文件中包含 JSX)或.ts
(如果没有 JSX)。
- 使用
-
类型定义:
- 为组件的 props 和 state 定义类型。这可以通过使用接口(interface)或类型别名(type)来实现。
- 在函数组件和类组件中使用 TypeScript 的类型定义来验证 props 和 state 的类型。
-
使用 TypeScript 特性:
- 利用 TypeScript 的类型注解、类型推断和类型检查等功能来提高代码的质量。
- 使用 TypeScript 的高级特性,如泛型、枚举和交叉类型等,来构建更加灵活和可复用的组件。
React 开发中有哪些最佳实践?
React 开发中有许多最佳实践可以帮助开发者提高代码质量、可维护性和性能。以下是一些常用的最佳实践:
- 组件化开发:将应用拆分成多个独立的、可复用的组件。这有助于降低代码的复杂性,并提高代码的可维护性。
- 状态管理:使用合适的状态管理工具(如 Redux、MobX 或 React 的 Context API)来管理应用的状态。这有助于避免组件之间的直接通信和状态混乱。
- 性能优化:使用 React 的性能优化技术,如 PureComponent、shouldComponentUpdate 和 React.memo 等,来避免不必要的渲染和性能瓶颈。
- 代码拆分和懒加载:使用 React 的代码拆分和懒加载功能来按需加载组件,从而减小应用的初始加载时间。
- 使用 TypeScript:如上所述,使用 TypeScript 可以提高代码的可读性和可维护性,同时提供类型检查和智能提示等功能。
- 遵循设计规范和最佳实践:遵循 React 的设计规范和最佳实践,如避免直接修改 props、使用 key 属性来优化列表渲染等。
- 测试:编写测试来验证组件的行为和交互。这有助于确保代码的正确性和稳定性。
以上内容仅供参考,如需更多信息,建议查阅 React 和 React Router 的官方文档或相关教程。
React 中,什么是合成事件?它的作用是什么?
React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。在 React 中,所有事件都是合成的,不是原生 DOM 事件,但可以通过 e.nativeEvent
属性获取 DOM 事件。
合成事件的主要作用是:
- 浏览器兼容:React 提供的合成事件用来抹平不同浏览器事件对象之间的差异,将不同平台事件模拟合成事件。
- 事件代理:React 采用的是顶层事件代理机制,能够保证冒泡一致性,可以跨浏览器执行。
- 性能优化:事件对象可能会被频繁创建和回收,因此 React 引入事件池,在事件池中获取或释放事件对象。即 React 事件对象不会被释放掉,而是存放进一个数组中,当事件触发,就从这个数组中弹出,避免频繁地去创建和销毁(垃圾回收)。
Redux 有哪些优缺点?
Redux 的优点包括:
- 单一数据源:Redux 使用单一的全局 state 树来管理整个应用的状态,这样可以确保状态的一致性和可预测性,减少了状态管理的复杂性。
- 可预测的状态变化:Redux 强制使用纯函数来更新状态,使得状态的变化可追踪和可预测,也使得应用的行为更容易理解和排查错误。
- 可维护性和可测试性:由于 Redux 严格限制了状态的变化方式,使得代码更易于维护和测试。状态的变化和副作用的处理都可以在纯函数中处理,方便编写单元测试。
- 中间件支持:Redux 提供了中间件机制,使得可以在状态更新的过程中执行额外的逻辑,非常适合处理异步操作、访问第三方 API 等。
Redux 的缺点包括:
- 学习曲线陡峭:Redux 的概念和使用方式需要一定的学习成本,尤其是对于初学者来说,理解和正确使用 Redux 可能需要一些时间和实践经验。
- 冗余代码:Redux 在使用上需要编写大量的模板代码,这使得代码变得冗余。尤其是当应用的状态管理相对简单时,使用 Redux 可能会显得有些过度。
- 性能开销:Redux 中状态的变化是通过创建新的状态副本来实现的,这可能导致性能开销。当应用状态树较大时,每次更新都会创建新的对象,影响性能。
Redux 的中间件是什么?有哪些常用的 Redux 中间件?
Redux 中间件是 Redux 提供的一个扩展机制,允许在 dispatch
一个 action 和到达 reducer 之间插入一些自定义的逻辑。这些中间件可以串联、组合,在一个项目中使用多个中间件。
常用的 Redux 中间件包括:
- redux-logger:一个用于记录日志的中间件,可以将 action 的相关信息输出到控制台,方便开发者进行调试。
- redux-thunk:一个用于处理异步操作的中间件,它允许 action 既可以是一个对象,也可以是一个返回函数的函数。在函数形式的 action 中,可以执行异步操作,并在异步操作成功后分发对象形式的 action 来更新状态。
- redux-devtools-extension:一个与 Redux DevTools 浏览器扩展集成的中间件,它提供了强大的调试功能,如时间旅行、查看 action 和 state 的历史记录等。
如何在 React 路由中实现动态加载模块,以实现按需加载?
在 React 中,可以使用 Webpack 的代码分割特性结合 React Router 来实现路由的动态加载和按需加载。这样可以减小应用的初始加载大小,提高首屏渲染速度。
实现方法通常包括以下几个步骤:
- 配置 Webpack:确保 Webpack 配置中启用了代码分割特性。
- 使用动态导入:在 React Router 的路由配置中,使用 Webpack 的动态导入语法
import()
来按需加载路由对应的组件。 - 配置异步组件:创建一个异步组件加载器,用于处理组件的加载和错误处理。
例如,在 React Router v4 中,可以这样配置动态加载:
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';const AsyncComponent = (importComponent) => {return (props) => (<div>{React.Suspense ? (<React.Suspense fallback={<div>Loading...</div>}>{React.lazy(importComponent)()}</React.Suspense>) : (<div>Loading...</div>)}</div>);
};const Home = AsyncComponent(() => import('./components/Home'));
const About = AsyncComponent(() => import('./components/About'));const App = () => (<Router><Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /></Switch></Router>
);export default App;
Redux 的 store 是什么?
Redux 中的 store 是一个核心概念,它是整个应用的状态存储中心。Store 是一个 JavaScript 对象,它保存了应用的全部状态,并通过创建 store 时传入的 reducer 函数来根据 action 更新状态。
在 Redux 应用中,所有组件的状态都存储在这个 store 中,这使得状态的变化可以预测和跟踪。Store 是通过 createStore
方法创建的,这个方法接受三个参数:reducer、初始状态(可选)和中间件(可选)。
什么是 React 的 useReducer? 它有什么作用?
useReducer
是 React 中用于高效管理复杂应用状态的钩子。它通过接受一个 reducer 函数和初始状态作为参数,提供了一种声明式的方式来更新和获取状态,从而使得状态管理更加清晰和灵活。
useReducer
的作用包括:
- 管理复杂状态:适用于具有深层结构和逻辑的状态管理场景。
- 增强可读性:通过事件驱动的方式来管理状态,增强了代码的可读性和可维护性。
- 方便调试:通过事件和状态变化的历史,可以更容易追踪状态流转的过程。
Redux 中如何重置状态?
在 Redux 中,可以通过在 reducer 中定义一个重置状态的 action 来实现状态的重置。具体步骤如下:
- 保存初始状态:在 store 初始化时,将初始状态保存到一个变量中。
- 定义重置 action:在 reducer 中,定义一个 type 为 “RESET” 的 action,其处理逻辑直接返回初始状态。
- 分发重置 action:在需要重置状态的时候,通过 store 的
dispatch
方法分发这个 RESET 的 action。
你在项目中是如何划分 React 组件的?
在项目中划分 React 组件时,通常会遵循以下原则:
- 单一职责原则:每个组件应该只负责一个单一的功能或视图部分,这样有助于提高组件的可重用性和可维护性。
- 高内聚低耦合:尽量使组件内部逻辑紧密相关,同时减少组件之间的依赖和耦合。
- 按功能划分:根据应用的功能模块来划分组件,如用户管理、订单管理等。
- 按层级划分:根据组件在 UI 层级结构中的位置来划分,如页面级组件、布局级组件和表单级组件等。
具体的划分方式会根据项目的实际情况和需求来确定。
什么是 React Router? 常用的 Router 组件有哪些?
React Router 是一个用于在 React 应用中实现路由管理的库。它允许开发者定义不同的路由,并将它们与对应的组件关联起来,从而实现页面的跳转和组件的加载。
常用的 Router 组件包括:
- BrowserRouter:用于在浏览器环境中提供路由功能,它使用 HTML5 的 History API 来实现 URL 的变化而不重新加载页面。
- HashRouter:与 BrowserRouter 类似,但它在 URL 中使用哈希(#)来表示路由路径。这种方式兼容性好,但不具备 BrowserRouter 的美观和搜索引擎优化优势。
- Route:用于定义单个路由规则,它接受一个 path 属性来指定路由路径,以及一个 component 属性来指定该路径对应的组件。
- Switch:用于包裹多个 Route 组件,并只渲染与当前 URL 匹配的第一个 Route 组件。
在 React 项目中如何使用 async/await?
在 React 项目中,async/await
通常用于处理异步操作,比如网络请求或读取文件。这些操作通常通过 JavaScript 的 Promise
来实现,而 async/await
提供了一种更简洁、更易读的语法来处理这些异步操作。
以下是一个使用 async/await
进行网络请求的示例:
import React, { useState, useEffect } from 'react';
import axios from 'axios';function DataFetcher() {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const fetchData = async () => {try {const response = await axios.get('https://api.example.com/data');setData(response.data);} catch (err) {setError(err);} finally {setLoading(false);}};fetchData();}, []);if (loading) return <div>Loading...</div>;if (error) return <div>Error: {error.message}</div>;return (<div><h1>Data:</h1><pre>{JSON.stringify(data, null, 2)}</pre></div>);
}export default DataFetcher;
在这个例子中,fetchData
是一个异步函数,它使用 await
来等待 axios.get
的结果。如果请求成功,它会更新组件的状态 data
;如果请求失败,它会更新 error
状态。最后,无论请求成功与否,它都会更新 loading
状态为 false
。
React 的 setState 的第二个参数作用是什么?
setState
是 React 中用于更新组件状态的方法。它的第一个参数是新的状态值或用于计算新状态的函数。第二个参数是一个可选的回调函数,它在状态更新并且组件重新渲染后被调用。
this.setState({ count: this.state.count + 1 }, () => {console.log('State updated, new count is:', this.state.count);
});
在这个例子中,当 count
状态更新后,回调函数会被调用,并且你可以在回调函数中访问更新后的状态。
React Router 的路由变化时,如何重新渲染同一个组件?
在 React Router 中,当路由变化但目标组件保持不变时,React Router 默认不会重新创建组件实例。为了在这种情况下重新渲染组件,你可以使用 React 的生命周期方法或 Hooks 来检测路由变化,并强制组件重新渲染。
一种常见的方法是利用 useLocation
Hook(在 React Router v6 中引入):
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';function MyComponent() {const location = useLocation();const [, forceUpdate] = useState();useEffect(() => {const handleLocationChange = () => {forceUpdate({});};handleLocationChange();const unlisten = history.listen(handleLocationChange);return () => {unlisten();};}, [location]);// 组件的其余部分return (<div>My Component</div>);
}
注意:上面的代码示例中,history.listen
是在 React Router v5 中使用的方法。在 React Router v6 中,你可以直接使用 useLocation
Hook 来监听位置变化,因为 useLocation
会在位置变化时返回一个新的值,从而触发组件的重新渲染。
React JsX 转换成真实 DOM 的过程是怎么样的?
-
Jsx 编译:首先,JSX 是一种 JavaScript 的语法扩展,允许你在 JavaScript 代码中写类似 HTML 的标记。在构建过程中,Babel 会将 JSX 编译成标准的 JavaScript 对象(React.createElement 调用)。
-
创建虚拟 DOM:React 使用这些 JavaScript 对象来创建一个轻量级的、内存中的表示(虚拟 DOM)。虚拟 DOM 是一个描述 UI 结构的对象树。
-
协调(Reconciliation):当状态或属性发生变化时,React 会创建一个新的虚拟 DOM 树。然后,它会比较新的虚拟 DOM 树和旧的虚拟 DOM 树之间的差异(这个过程称为协调)。
-
应用差异:一旦确定了差异,React 就会更新真实 DOM 以反映这些变化。React 只会更新那些真正需要改变的部分,这大大提高了性能。
这个过程是 React 的核心,它允许 React 以高效的方式更新 UI,即使面对复杂的应用程序也是如此。
React 中的 setState 是同步还是异步的?为什么 state 的更新不一定是同步的?
在React中,setState方法的行为既有同步的也有异步的,这主要取决于其使用方式和场景。
- 通常情况下,setState是异步执行的。当调用setState时,React并不会立即更新组件state的值,而是将这个更新动作放到一个队列中,等待合适的时机再去执行。这样可以避免频繁的重新渲染,提高性能。
- 在某些特定场景下,如生命周期函数componentDidUpdate和回调函数中调用setState,它可能是同步执行的。此时,React会立即更新组件state的值,并且会触发重渲染。
React的setState看上去是异步的,但实际上是因为React的合成事件和生命周期钩子的调用顺序在状态更新之前,导致在合成事件和钩子函数中无法立即拿到更新后的值,从而形成了所谓的“异步”。不过,如果需要在状态更新后立即执行某些操作,可以使用setState的回调函数或componentDidUpdate生命周期函数。
React 是如何判断何时重新渲染组件的?
React通过比较组件的当前状态(state)和属性(props)与之前的状态和属性,来决定是否需要重新渲染组件。
- 当调用setState方法时,React会将新的状态合并到组件的状态队列中,并在未来的某个时间更新组件的状态。一旦状态更新,React会检查这个更新是否导致组件的输出(即渲染的虚拟DOM)发生变化。
- 如果检测到变化,React会重新渲染该组件及其子组件,以反映新的状态。
- React还使用了一种称为“批量更新”的机制,可以将多个更新操作合并为一个,减少不必要的重复渲染,提高性能。
如何提高 React 列表渲染的性能?
提高React列表渲染性能的方法有多种,包括但不限于:
- 使用key属性:在使用map方法渲染列表时,给每个列表项添加唯一的key属性。React可以使用key来快速确定哪些项需要更新,从而提高性能。
- 使用PureComponent或memo:如果列表项是一个纯函数组件,可以使用React的PureComponent或memo来防止不必要的重新渲染。
- 使用shouldComponentUpdate:如果列表项是一个类组件,可以手动实现shouldComponentUpdate生命周期方法,来判断是否需要重新渲染。
- 使用虚拟化技术:当列表项数量非常大时,可以使用虚拟化技术(如React Virtualized库或React Window库)来只渲染可见的列表项,从而提高性能。
- 使用Immutable数据结构:可以避免每次更新都创建新的对象或数组,减少不必要的渲染。
React 的 key 属性的作用是什么?为什么要添加 key?key 主要解决了什么问题?
在React中,key属性用于帮助React识别哪些列表中的项已经被修改、添加或删除。
- 作用:当列表中的项被重新排序或修改时,React使用key属性来确定每个项的唯一标识,以便有效地更新页面上的内容。
- 必要性:如果没有key属性,React在更新列表时可能会丢失项的状态,或者错误地复用先前的元素,导致一些无法预料的行为。
- 解决的问题:key属性可以确保React正确地维持每个项的状态,避免数据丢失或错误的结果。同时,它还可以提高性能,因为React可以使用key来快速定位需要更新的项,而不是重新渲染整个列表。
React 应用的打包和发布过程是什么?
React应用的打包和发布过程通常包括以下几个步骤:
- 确保项目代码已经完成并通过测试:可以正常运行。
- 运行打包命令:在项目根目录下运行如
npm run build
的命令,该命令会自动执行打包操作,生成一个包含静态文件的build
文件夹。 - 部署静态文件:使用FTP或其他文件传输工具将
build
文件夹中的静态文件上传到服务器。 - 配置Web服务器:在服务器上配置如Nginx或Apache的Web服务器,将服务器根目录指向打包生成的静态文件所在的目录。
- 配置域名或IP地址:使得用户可以通过浏览器访问到项目。
- 访问项目:部署完成后,通过访问服务器的域名或IP地址即可查看项目的效果。
如何解决 React 中 props 层级过深的问题?
解决React中props层级过深的问题有多种方法,常见的方法包括:
- 使用Context API:Context提供了一种在组件树中传递数据的方式,而不必在每个层级上手动传递props。
- 使用全局状态管理库:如Redux、MobX等,它们可以在整个应用中存储和管理状态,从而避免通过props在组件之间传递状态。
- 使用组合式组件:将大型组件拆分为更小的、可重用的组件,并通过props将必要的数据传递给子组件。
从旧版本的 React 升级到新版本时,可能会有哪些问题?
从旧版本的React升级到新版本时,可能会遇到以下问题:
- API变更:新版本可能会引入新的API或弃用旧的API,需要更新代码以适应这些变更。
- 性能问题:新版本可能会对性能进行优化或引入新的性能问题,需要进行性能测试和调优。
- 依赖项不兼容:第三方库可能与新版本的React不兼容,需要更新或替换这些库。
- 代码重构:为了利用新版本的新特性和改进,可能需要对代码进行重构。
为了解决这些问题,建议在升级前仔细阅读React的升级指南和发行说明,了解新版本的变化和迁移步骤。同时,可以在开发环境中逐步升级和测试,以确保应用的稳定性和性能。
React状态管理工具对比⭐⭐⭐
在React项目中,全局状态管理工具的选择对于应用的性能、可维护性和开发效率都至关重要。以下是一些常见的React全局状态管理工具的详解:
Redux
-
概述
Redux是JavaScript应用中管理应用状态的工具,特别适用于复杂的、需要共享状态的中大型应用。Redux的核心思想是将应用的所有状态存储在一个单一的、不可变的状态树(state tree)中,状态只能通过触发特定的action来更新。
-
核心概念
- Store:存储应用的全局状态,应用中只能有一个store。
- Action:描述发生了什么事情,通常是一个包含type和payload的对象。
- Reducer:纯函数,接收当前的state和action,返回一个新的state。
- Dispatch:发送action到reducer以触发状态的变化。
- Middleware:拦截action,可以用于异步操作(如redux-thunk)或日志记录。
-
使用示例
Redux的使用通常包括定义store、创建slice(使用Redux Toolkit)、在React组件中使用Provider组件将store注入到组件树中、使用useSelector和useDispatch钩子访问和更新状态等步骤。
MobX
-
概述
MobX是一款简单易用的状态管理插件,它采用了响应式编程的思想。使用MobX,可以轻松地管理应用的状态,并且无需复杂的中间件和配置。
-
核心概念
- State:状态。
- Actions:动作,用于修改状态。
- Derivations:派生值,基于状态计算得到的值。
-
特点
- 区分了应用程序中的状态、动作和派生值。
- 所有的派生值将在状态改变时自动且原子化地更新。
- 提供了丰富的工具和扩展,如React装饰器、副作用等。
SimpleR State
-
概述
SimpleR State是一个为React量身定做的超轻量级状态管理库,它摒弃繁复,回归最纯粹的状态更新体验。
-
特点
- 极简主义为核心,将复杂的概念和冗余代码降到最低。
- 引入React Hooks的现代性,实现了状态管理的新高度——简洁、快速且易测试。
- 最小化API设计,直觉式的API让开发者迅速掌握。
- 纯函数更新,无论是同步还是异步,只需通过普通函数即可完成状态变更。
- 提供了广泛的定制空间和单元测试友好的特性。
Recoil
-
概述
Recoil是Facebook开源的一款状态管理库,旨在提供一套更简单、更直观的状态管理方案。
-
核心概念
- Atoms:原子状态,Recoil中的基本状态单元。
- Selectors:选择器,用于从Atoms中派生出新的状态。
- Stores:存储,类似于Redux中的store,但更轻量级。
-
特点
- 为每一个原子状态提供了独立的存储,让状态的读写变得更加直接和高效。
- 提供了丰富的API,支持状态的订阅和事件的触发。
- 状态管理更加灵活和强大。
Valtio
-
概述
Valtio是专门为React设计的状态管理库,它提供了一种简洁、直观的方式来管理应用的状态。
-
特点
- 使用Proxy对象来实现状态的观察和变化。
- 让状态的读写变得更加直观和高效。
- 支持时间旅行和状态的持久化。
- 状态管理变得更加灵活和强大。
React 状态管理工具是帮助开发者在 React 应用中高效管理组件状态的工具。它们可以解决组件间状态共享、全局状态管理和性能优化等问题。以下是常用的 React 状态管理工具及其详细介绍:
React Context
React 自带的状态管理工具,适合处理简单的全局状态。通过 Context.Provider
和 useContext
实现组件间的状态共享。
-
内置工具,无需额外安装。
-
简单易用,但性能优化需要额外实现(如
React.memo
)。 -
不适合复杂的状态逻辑或大规模项目。
-
主题切换、语言设置等全局状态。
比较总结表格:
工具名称 | 学习难度 | 特点 | 使用场景 | 性能优化 | 生态系统 |
---|---|---|---|---|---|
React Context | 低 | 内置工具,轻量,适合简单全局状态共享 | 小型项目 | 手动优化 | 内置工具 |
Redux | 高 | 单向数据流,生态成熟,调试工具强大 | 大型复杂项目 | 高性能 | 非常丰富 |
MobX | 中 | 响应式,灵活,但可能数据流复杂 | 中小型项目 | 自动优化 | 成熟 |
Zustand | 低 | 轻量化,不依赖 Context,API 简单 | 小型项目或局部状态管理 | 高性能 | 一般 |
Recoil | 中 | 原子化状态管理,异步支持 | 中型项目 | 高性能 | 逐步完善 |
Jotai | 低 | 极简 API,轻量原子化 | 小型项目 | 高性能 | 一般 |
XState | 高 | 基于状态机,支持复杂逻辑和可视化 | 多步骤流程或复杂逻辑 | 自动优化 | 成熟 |
根据项目需求选择合适的状态管理工具:
- 简单全局状态:React Context 或 Zustand。
- 大型复杂项目:Redux。
- 中型项目:Recoil 或 MobX。
- 多步骤复杂逻辑:XState。
这些全局状态管理工具各有优缺点,开发者在选择时应根据项目的规模、复杂度、团队的技术栈和偏好等因素进行综合考虑。同时,了解每种工具的核心概念和使用方法也是非常重要的。
相关文章:
React进阶面试题目(三)
如何在 React 中实现滚动动画? 在 React 中实现滚动动画可以通过多种方式实现,以下是一个基本的实现步骤: 构建组件:首先构建需要展示滚动动画的组件,例如一个 About 组件,它包含一些文本或元素。监听滚动…...
每日计划-1129
1. 完成 200. 岛屿数量 class Solution { private:void dfs(vector<vector<char>>& grid,int r,int c){int nrgrid.size();int ncgrid[0].size();grid[r][c]0;if (r - 1 > 0 && grid[r-1][c] 1) dfs(grid, r - 1, c);if (r 1 < nr && …...
杭州网世一站式网络解决方案,助力安邦护卫网络升级改造
随着信息技术的不断进步,浙江台州安邦护卫有限公司现有的网络设备已无法满足其日益增长的业务需求。网络性能瓶颈、安全隐患和管理复杂性等问题逐渐凸显,严重影响了企业的运营效率和服务质量。为了解决这些问题,浙江台州安邦护卫有限公司决定…...
vue3.0 根据富文本html页面生成压缩包(含视频在线地址、图片在线地址、前端截图、前端文档)
vue3.0生成压缩包(含在线地址、前端截图、前端文档) 需求描述效果开始下载插件包基本代码构造 点击下载按钮1.截图content元素,并转化为pdfcanvas putImageData、getImageDatagetImageData 获取指定矩形区域的像素信息putImageData 将这些数据…...
从0开始学PHP面向对象内容之常用设计模式(享元)
二、结构型设计模式 7、享元模式(Flyweight Pattern) 这里是引用享元模式(Flyweight Pattern) 是一种结构型设计模式,旨在通过共享对象来减少内存使用,尤其适用于大量相似对象的场景。通过共享和重用对象的…...
Idea 2024.3 突然出现点击run 运行没有反应,且没有任何提示。
写这篇文章的目的是为了提供一个新的解决思路,因为存在同病不同原因。 如果你进行了1. 检查运行配置 (Run Configuration) 2. 清理和重建项目 3. 清除缓存并重启 IDEA 4.排除kotlin 5.重装idea等等操作之后仍然没有解决,可以试着按一下步骤进行解决。 检…...
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
作者:陈承 背景 在 2018 年的 2 月,ARMS Java Agent 的第一个版本正式发布,为用户提供无侵入的的可观测数据采集服务。6 年后的今天,随着软件技术的迅猛发展、业务场景的逐渐丰富、用户规模的快速增长,我们逐渐发现过…...
【Linux】开发工具
这篇文章主要涉及sudo指令进行提权的方法,gcc/g的使用并且提及了一些make、makefile sudo指令 在前几篇文章中,我们先后了解了对于不同的角色来说,可以进行不同的操作,而对于新建的普通用户是不能进行权限提升的,这是…...
网络通信基础:TCP/IP、UDP、三次握手、Socket与HTTP协议详解
在网络通信的世界中,TCP/IP、UDP、三次握手、Socket和HTTP协议是不可或缺的基本概念。它们构成了网络通信的基石,对于理解网络编程和设计网络应用程序至关重要。本文将详细介绍这些概念,帮助读者更好地理解网络通信的原理。 首先,…...
(Python)前缀和
前缀和: 前缀和预先计算并存储一系列连续元素的总和,是一种优化技巧,提高算法效率。记录一个数组中各下标位置之前的所有元素的总和,本文对应下标的总和中不含对应下标元素本身。若有需要也可以对应下标记录的总和包含下标本身元…...
【Linux】-操作系统
🔑🔑博客主页:阿客不是客 🍓🍓系列专栏:深入代码世界,了解掌握 Linux 欢迎来到泊舟小课堂 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 一、冯•诺依曼架构ÿ…...
shell echo双引号和单引号区别
echo双引号"" var1"a" var2"b" echo -e "$var1\t$var2"输出: 使用双引号 "" 时,变量会被正确解析。 echo单引号‘’ var1"a" var2"b" echo -e $var1\t$var2输出: …...
嵌入式QT学习第3天:UI设计器的简单使用
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Qt Creator 里自带的 Qt Designer,使用 Qt Designer 比较方便的构造 UI 界 面。 在 UI 文件添加一个按钮 左边找到 Push Button,然后拖拽到中…...
Nuxt.js 应用中的 render:response 事件钩子
title: Nuxt.js 应用中的 render:response 事件钩子 date: 2024/11/29 updated: 2024/11/29 author: cmdragon excerpt: render:response 是一个在 Nuxt.js 中与服务器端渲染(SSR)相关的钩子,它会在请求的响应发送之前被调用。这个钩子的目的是让开发者可以在响应发送之…...
Node报错:npm error code ETIMEDOUT
1、报错详细信息 npm error code ETIMEDOUT npm error syscall connect npm error errno ETIMEDOUT npm error network request to https://registry.npmjs.org/express failed, reason: connect ETIMEDOUT 104.16.1.35:443 npm error network This is a problem related to ne…...
领域驱动设计(DDD)模式深度剖析与 C# 实践
一、DDD 模式概述 领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件开发方法论,旨在应对复杂业务领域的软件系统构建挑战。它强调以领域模型为核心,围绕业务领域中的关键概念、规则以及它们之间的关系来组织软…...
2024“蜀道山” RE 部分题解
Map_maze 题目描述 真真假假真真,你能够寻找到最后的终点吗? 附件下载 迷宫生成 v5 是一个长度为 105 的数组,被用作 15x15 的二维网格 int __cdecl sub_4010D0(_DWORD *a1, _DWORD *a2) {_DWORD *v2; // eax_DWORD *v3; // eaxint result; // eax_DWORD v5[1…...
composition
议论文 三个段落 第一段:2-3句话((1)引出背景(2)提出问题(3)过渡句) 第一段 (1)引出背景 As the giant leap of __(society,technology,education,culture,medical se…...
前端开发:构建高质量用户体验的全方位指南(含实际案例与示例)
前端开发:构建高质量用户体验的全方位指南(含实际案例与示例) 在当今数字化时代,前端技术不仅是网页和应用的门面,更是连接用户与数字世界的桥梁。一个高质量的前端开发项目不仅能够提升用户体验(UX&#…...
从Facebook的技术演进看社交媒体的未来趋势
在过去的二十年里,Facebook(现为Meta)从一个大学校园中的社交平台发展成了全球最大的社交媒体网络之一,成功塑造了人们交流、分享和消费信息的方式。作为社交媒体的巨头,Facebook的技术演进不仅推动了平台自身的发展&a…...
Linux下的wlan0控制
WIFI常用的两种模式:STA / AP 1. STA模式:客户端 嵌入式的系统下常常要手动配置wifi,和IP地址才能开始上网,关于STA模式下,常用的wifi配置工具有wpa_supplicant和轻量级的udhcpc客户端。 1.1wpa_supplicant 最小配置…...
常用循环依赖解决方案
常用循环依赖解决方案 Spring框架在4.3版本开始引入了对循环依赖的更好支持,但在此之前,Spring已经提供了一些机制来处理循环依赖。 实际上,Spring从一开始就提供了几种解决循环依赖的方法,只是在后续版本中对这些机制进行了优化…...
HTTPTomcatServlet
今日目标: 了解JavaWeb开发的技术栈理解HTTP协议和HTTP请求与响应数据的格式掌握Tomcat的使用掌握在IDEA中使用Tomcat插件理解Servlet的执行流程和生命周期掌握Servlet的使用和相关配置1,Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网,也称为万维网(www),能够通过浏览…...
instanceof运算符
而instanceof可以精准判断数据类型...
Conda 管理python开发环境
同步发布于我的网站 🚀 故事起因: 在公司使用Requests多任务并行开发时遇到了问题,使用 ProcessPoolExecutor 时不能正常发出网络请求,会卡在网络请求发不出去,但是善于用 ThreadPoolExecutor 时是可以的,纠结了很久,一…...
uniapp关闭sourceMap的生成,提高编译、生产打包速度
警告信息:[警告⚠] packageF\components\mpvue-echarts\echarts.min.js 文件体积超过 500KB,已跳过压缩以及 ES6 转 ES5 的处理,手机端使用过大的js库影响性能。 遇到问题:由于微信小程序引入了mpvue-echarts\echarts.min.js&…...
服务器挖矿
文章目录 一、确定挖矿进程并停止二、查找并清除挖矿相关文件三、检查并修复系统漏洞四、加强安全防护 一、确定挖矿进程并停止 查找挖矿进程 在Linux系统中,可以使用命令如top或htop来查看系统资源占用情况。挖矿程序通常会占用大量的CPU或GPU资源。例如ÿ…...
Flink双流Join
在离线 Hive 中,我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢?Flink DataStream API 为我们提供了3个算子来实现双流 join,分别是: join coGroup intervalJoin 下面我们分别详细看一下这…...
.net XSSFWorkbook 读取/写入 指定单元格的内容
方法如下: using NPOI.SS.Formula.Functions;using NPOI.SS.UserModel;using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;using OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric;/// <summary>/// 读取Excel指定单元格内容/// </summa…...
【VUE3】【Naive UI】<NCard> 标签
【Vue3】【Naive UI】 标签 title 属性bordered 属性header-style 和 body-style 属性footer 属性actions 属性hoverable 属性loading 属性size 属性type 属性cover 和 avatar 属性description 属性style 属性 【VUE3】【Naive UI】<NCard> 标签 【VUE3】…...
喜欢发光的自己
Music: 听见下雨的声音 想着写点什么吧...从哪开头好呢?... 好像有很多话想记录下来,但又不知道从哪开头 自上次写博客至现在已经有段时间了。 最近还发生了挺多事,自己的身体又将面临一次考验... 有颗蛀牙,但莫名奇妙的是里…...
mfc110u.dll是什么意思,mfc110u.dll丢失解决方法大全详解
mfc110u.dll是Microsoft Foundation Classes (MFC)库的一个特定版本(版本11.0)的Unicode动态链接库文件。MFC是Microsoft为C开发者设计的一个应用程序框架,主要用于简化Windows应用程序的开发工作。这个框架封装了很多Windows API函数&#x…...
制片人欧阳行远:引领独立电影斩获国际殊荣
随着全球电影市场对独特叙事和多元化题材的需求持续高涨,独立电影再次成为业内外讨论的焦点,尤其是聚焦亲情、成长经历和女性视角的影片,在国际影坛掀起了一股热潮。这一趋势的形成,离不开一些杰出短片的奠基作用,而欧阳行远作为执行制片人,凭借敏锐的行业嗅觉和出色的制作能力…...
《C++ Primer Plus》学习笔记|第7章-函数——C++编程模块 (未完结)
文章目录 7.1 函数的基本知识7.1.1 定义函数7.1.2 函数原型和函数调用 7.2 函数参数和按值传递7.3 函数与数组7.3.5 指针与const7.4 函数和二维数组 7.10 函数指针1. 函数的地址2. 声明函数指针3.使用指针来调用函数 7.12 复习题1. 使用函数的3个步骤是什…...
C/C++ 数据结构与算法【线性表】 顺序表+链表详细解析【日常学习,考研必备】带图+详细代码
1)线性表的定义 线性表(List):零个或多个数据元素的有限序列。 线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素…...
详细说说 JDK 的线程池的创建参数
文章目录 1. 概要2. 线程的核心参数2.1.核心线程和最大线程2.2.任务队列2.2.1.ArrayBlockingQueue2.2.2.LinkedBlockingQueue2.2.3.SynchronousQueue2.2.4.PriorityBlockingQueue2.2.5.DelayQueue2.2.7.LinkedBlockingDeque 2.3 keepAliveTime2.4 ThreadFactory2.5 拒绝策略 3.…...
惠普电脑切换默认F1至F12快捷键,FN切换
发现新买的惠普电脑,按F1至F12发现是快捷功能键,而按fnF1至F12才是windows的功能键和正常我自己使用的电脑刚好相反,实在太不方便了。 解决办法需要进入biso里面去把功能键模式选中给关掉,才能恢复回来...
RabbitMQ在手动消费的模式下设置失败重新投递策略
最近在写RabbitMQ的消费者,因为业务需求,希望失败后重试一定次数,超过之后就不处理了,或者放入死信队列。我这里就达到重试次数后就不处理了。本来以为很简单的,问了kimi,按它的方法配置之后,发…...
[巅峰极客 2021]签到
[巅峰极客 2021]签到 给了我们好多表情,真的是一脸懵逼 注意给我们的关键词 GAME 现在还不知道是什么意思我们去试着解开一下 用这个emoji表情解密器,这里我找了好久才找到一个 emoji-aes 这里的Key值就是GAME 运行后出现flag NSSCTF{10ve_4nd_Peace…...
CrystalDiskInfo:硬盘健康监测工具简介和下载
原论坛给你更好的阅读体验:CrystalDiskInfo:硬盘健康监测工具简介和下载 | 波波论坛 引言 在日常使用电脑时,硬盘的健康状态对于系统的稳定性和数据的安全性至关重要。硬盘出现故障可能会导致数据丢失,严重时甚至会使整个系统无…...
循环神经网络(RNN)详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
vue基础之3:模板语法、数据绑定
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
Ubuntu通过脚本启动多个可执行文件
Ubuntu通过脚本启动多个可执行文件 在 Ubuntu 中,可以通过一个脚本启动多个可执行文件,同时支持顺序执行、并行执行或特定条件下的执行。以下是实现的详细方法: 1. 创建脚本文件 首先,创建一个脚本文件,例如 start_p…...
【C++】LeetCode:LCR 026. 重排链表
题干 LCR 026. 重排链表 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → … 不能只是单纯的改变节点内部的值,而是需要实…...
文档加密怎么做才安全?
公司的文档包含很多机密文件,这些文件不仅关乎公司的核心竞争力,还涉及到客户隐私、商业策略等敏感信息。因此,文档的保管和传递一直是我们工作的重中之重。 为了确保机密文件的安全,公司需要制定了一系列严格的保密措施。从文件的…...
CTF之WEB(php弱类型绕过)
PHP 的弱类型特性有时会导致意外的行为,特别是在类型比较时。这些特性可以被利用来绕过一些预期的安全检查。以下是一些常见的 PHP 弱类型绕过技巧及其解释: 类型介绍 1. 类型比较 ( vs ) 在 PHP 中, 是松散比较,而 是严格比较…...
Java ConcurrentHashMap
Java Map本质不是线程安全的,HashTable和Collections同步包装器(Synchronized Wrapper)在并发场景下性能低。Java还为实现 Map 的线程安全提供了并发包,保证线程安全的方式从synchronize简单方式到精细化,比如Concurre…...
力扣162:寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。 给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。 你可以假设 nums[-1] nums[n] -∞ 。 你必须实现时间复杂度为 O(…...
网络设备配置指南:交换机、路由器与防火墙的基础配置与管理
在现代网络管理中,交换机、路由器和防火墙是不可或缺的关键设备。掌握这些设备的基本配置与管理,对于确保网络的稳定性、安全性和高效性至关重要。本文将详细介绍交换机、路由器和防火墙的基础配置与管理,并通过代码示例和图示来帮助读者更好地理解和应用。 一、交换机的基…...
parallelStream并行流使用踩坑,集合安全
parallelStream并行流使用踩坑 parallelStream介绍 parallelStream实现的是多线程处理从而实现并行流,相较于stream的单行流处理数据的速度更快,看一下其源码会发现parallelStream是使用线程池ForkJoin来调度的。 而ForkJoinPool的默认线程数是CPU核数 …...