react中概念性总结(四)

发布时间:2024年01月12日

目录

React如何做性能优化,最少说出四点?

虚拟dom一定比真实dom快吗,为什么?

说说你对事件循环的理解?

React路由传递参数的方式?

简述React的生命周期函数及含义?

说说react 中jsx语法糖的本质?

React的路由跳转方式有哪些?

在React中,可以使用PropTypes库来进行props的校验,

React中的高阶组件是什么

Css3中如何使用媒体查询?响应式布局如何实现

Context状态树的执行流程?

Redux在大型项目中目录结构你一般可以怎么划分呢?


React如何做性能优化,最少说出四点?

1) 可以通过shouldconponentUpdate和react.memo方法来进行性能优化,shouldcomponentUpdate是react中的生命周期

2) 使用key来进行性能优化:key是表示唯一的值,它可以实现只渲染可见区域的内容,解除对数据的繁杂性

3)使用react的虚拟化组件:对于组件或表格等需要大量数据的场景,可以使用react的虚拟化组件。可以大大减少内存的占用,提高性能

4)使用react懒加载和代码拆分:将应用程序拆分为多个按需加载的模块,可以减少初始化加载时间,并在需要时动态加载额外的代码。

5)React提供了react.lazy和suspense组件实现

虚拟dom一定比真实dom快吗,为什么?

虚拟 DOM 的主要作用是优化渲染性能,在某些情况下可以比直接操作真实 DOM 更快,但也不是一定比真实 DOM 快,具体原因如下:

  1. 初始化渲染:虚拟 DOM 首次渲染时,需要先构建虚拟 DOM 树,然后再将其转换为真实 DOM,这个过程会使得虚拟 DOM 的渲染速度略慢于直接操作真实 DOM。

  2. 更新渲染:虚拟 DOM 的优势体现在更新渲染上,当组件的状态改变时,虚拟 DOM 把组件内部的状态变化转换成一系列可执行的 DOM 操作,再将这些操作一次性完成,比直接对真实 DOM 进行增删改的操作速度更快,减少了对真实 DOM 的多次操作。

  3. 算法复杂度:虚拟 DOM 更适合大规模的数据集合的渲染,因为它采用了一些复杂度较高的算法来实现最小化渲染,而对于少量数据更新,可能其算法复杂度高于直接操作真实 DOM,所以虚拟 DOM 并不一定比真实 DOM 更快。

综上所述,使用虚拟 DOM 可以在某些情况下提高性能,但它与真实 DOM 并非绝对的快慢关系,具体取决于应用场景和数据规模等因素。在实际使用中,可以根据具体情况选择使用虚拟 DOM 还是直接操作真实 DOM 来实现更优的性能。

说说你对事件循环的理解?

事件循环是 JavaScript 引擎中用于处理异步任务的一种机制。JavaScript 是单线程的语言,即一次只能处理一个任务,而异步任务的执行不会阻塞主线程,因此需要一个机制来处理这些异步任务,并将其放入任务队列中,等待主线程空闲时执行。

事件循环的基本原理如下:

  1. 主线程执行同步任务,遇到异步任务(如定时器、AJAX 请求、事件监听等)时,将其注册并继续执行后续同步任务。

  2. 当异步任务条件满足(如定时器时间到、AJAX 请求完成、用户触发事件等)时,将其对应的回调函数放入任务队列中。

  3. 主线程执行完同步任务后,检查任务队列是否为空,若不为空,则按照一定规则从任务队列中取出一个任务(通常是先进先出),放入主线程执行。

  4. 主线程执行任务时,可能还会产生新的异步任务,重复上述过程。

整个事件循环过程中,主线程不断地从任务队列中取出任务执行,这个过程不断重复,也称为事件循环。异步任务的执行顺序是通过事件循环机制保证的。

事件循环的参与者包括以下三个主要组件:

  1. 主线程:用于执行同步任务,包括初始化执行、函数调用、表达式运算等。

  2. 任务队列(Task Queue):用于存放待执行的回调函数,分为宏任务队列(Macro Task Queue)和微任务队列(Micro Task Queue)。

  3. 事件触发线程:用于产生异步任务,如定时器触发器、鼠标事件触发器等。

事件循环的理解对于理解 JavaScript 异步编程非常重要。它帮助我们理解异步任务是如何被捕获和处理的,以及如何避免出现长时间阻塞主线程,从而提高应用的性能和用户体验。

React路由传递参数的方式?

在 React 中,有几种方式可以路由传递参数:

  1. URL 参数:可以使用 React Router 的路由参数来传递参数。在定义路由时,使用 :parameter 的形式指定参数名,在组件中可以通过 props.match.params 来获取参数值。

示例代码:

<Route path="/user/:id" component={UserComponent} />

UserComponent 组件中,可以通过 this.props.match.params.id 获取参数值。

查询字符串参数:可以通过 location.search 获取查询字符串参数,并使用 URLSearchParams API 或其他库来解析参数。

示例代码:

// URL: /user?id=123&name=John
const params = new URLSearchParams(this.props.location.search);
const id = params.get('id'); // 获取 id 参数值
const name = params.get('name'); // 获取 name 参数值
  1. 路由状态参数:可以通过 history 对象的 pushreplace 方法传递参数。使用 state 属性来传递参数,在组件中可以通过 location.state 获取参数值。

示例代码:

// 通过路由跳转传递参数
this.props.history.push({
 ?pathname: '/user',
 ?state: { id: 123, name: 'John' }
});
?
// 在 UserComponent 组件中获取参数值
const id = this.props.location.state.id;
const name = this.props.location.state.name;

需要注意的是,路由参数的传递方式取决于具体的需求和场景。URL 参数适合表示资源的唯一标识符,查询字符串参数适合表示可选参数,而路由状态参数适合表示较大的数据或跳转前后状态的保存。

以上是一些常用的路由传递参数的方式,在实际开发中可以根据需求选择适合的方式。

简述React的生命周期函数及含义?

1)挂载阶段:

constructor:组件初始化时调用,可以在此函数中进行状态的初始化和绑定事件处理函数。

static getDerivedStateFromProps:在组件实例化和重新渲染之前调用,用于根据新的props来更新state。返回一个对象来更新state,或者返回null不更新state。

render:根据state和props来渲染组件的UI,必须返回一个React元素或null。

componentDidMount:组件已经被渲染到真实的DOM中后调用,可以进行一些副作用操作,例如请求数据、订阅事件等。

2)更新阶段:

static getDerivedStateFromProps(props, state):同挂载阶段中的生命周期函数。

shouldComponentUpdate:在组件更新之前调用,用于确定是否重新渲染组件。可以根据新旧props和state来决定是否需要更新组件,默认返回true。

render:同挂载阶段中的生命周期函数。

getSnapshotBeforeUpdate:在调用render之后,在更新DOM之前调用,给组件获取即将更新的信息(例如滚动位置),返回值将会作为componentDidUpdate的第三个参数。

componentDidUpdate:在组件更新之后立即调用,可以进行一些副作用操作。

3)销毁阶段:

componentWillUnmount:组件将要被卸载和销毁之前调用,可以在此函数中进行清理操作。

说说react 中jsx语法糖的本质?

JSX 是 React 中一种特殊的语法,它允许开发人员在 JavaScript 代码中使用类似 HTML 的标记来描述 UI 界面的结构和行为。JSX 本质上是一种语法糖,它被编译器转化为 React.createElement() 函数的调用。

例如,下面是一个使用 JSX 的 React 组件:

function MyComponent(props) {
 ?return (
 ? ?<div className="my-component">
 ? ? ?<h1>{props.title}</h1>
 ? ? ?<p>{props.subtitle}</p>
 ? ?</div>
  )
}

在编译器中,上述代码会被转化为如下的 JavaScript 代码:

function MyComponent(props) {
 ?return React.createElement(
 ? ?"div",
 ?  { className: "my-component" },
 ? ?React.createElement("h1", null, props.title),
 ? ?React.createElement("p", null, props.subtitle)
  );
}

这种转化过程中,JSX 元素会被转化为 React.createElement() 函数的调用,该函数接受三个参数:元素类型、元素属性和子元素。在运行时,React 可以通过这些参数来创建真正的 DOM 元素并将其渲染到页面上。因此,JSX 本质上只是一种简化了语法的方式,方便开发人员编写 React 组件,提高了代码的可读性和可维护性。

React的路由跳转方式有哪些?

在 React 中,可以使用多种方式进行路由跳转。以下是一些常用的方式:

  1. React Router: React Router 是一个常用的 React 路由库,提供了一套完整的路由解决方案。它支持使用 <BrowserRouter><HashRouter> 组件来创建路由容器,并使用 <Route><Link><Switch> 等组件来定义和管理路由。

  2. 静态跳转:在某些情况下,你可以直接使用 <a> 标签进行静态跳转。例如:<a href="/about">About</a>。然而,这种静态跳转方式会导致整个页面刷新,不适用于单页应用。

  3. 使用编程式导航:React Router 提供了一些导航方法,可以在组件中使用编程式导航。例如,使用 history.push('/about')history.replace('/about') 可以在路由间进行导航。

  4. 使用 Link 组件:React Router 提供了 <Link> 组件,它可以渲染为包含导航功能的链接。可以通过设置 to 属性来指定导航目标的路径。例如:<Link to="/about">About</Link>

  5. 使用 NavLink 组件:<NavLink><Link> 的一个扩展版本,它可以为匹配当前路由的链接添加活动状态的样式类。可以通过 activeClassName 属性来指定活动状态下的样式类名。

在React中,可以使用PropTypes库来进行props的校验,

它可以用于检查组件接收到的props的数据类型是否符合预期。以下是一些常用的数据类型校验方法:

  1. PropTypes.string: 校验props是否为字符串类型。

  2. PropTypes.number: 校验props是否为数字类型。

  3. PropTypes.bool: 校验props是否为布尔类型。

  4. PropTypes.array: 校验props是否为数组类型。

  5. PropTypes.object: 校验props是否为对象类型。

  6. PropTypes.func: 校验props是否为函数类型。

  7. PropTypes.element: 校验props是否为React元素(即JSX)类型。

  8. PropTypes.instanceOf: 校验props是否为指定的类的实例。

  9. PropTypes.oneOf: 校验props是否为指定值中的一个。

  10. PropTypes.oneOfType: 校验props是否为指定类型中的一种。

  11. PropTypes.arrayOf: 校验props是否为指定类型的数组。

  12. PropTypes.objectOf: 校验props是否为指定类型的对象。

  13. PropTypes.shape: 校验props是否符合指定的对象形状。

React中的高阶组件是什么

React中的高阶组件是一个函数,它接受一个组件作为输入,并返回一个新的组件作为输出。这个新的组件可以增强原来的组件,例如添加新的props、修改现有的props、渲染劫持、给组件添加生命周期等等。以下是一些常用的高阶组件:

  1. withRouter: 用于将react-router的路由信息注入到组件props中,让组件可以访问路由信息。

  2. connect: 是react-redux库中的高阶组件,用于连接组件和Redux store,将store中的state和dispatch映射到组件的props中。

  3. React.memo: 一个HOC用于将结果缓存起来以提高组件性能,默认情况下只会浅层比较props的变化。

  4. React.forwardRef: 一个HOC用于将ref传递给子组件。

  5. Redux-saga中的saga hoc: 可以通过该HOC将saga函數作为prop傳遞給组件,从而实现组件与saga的解耦。

使用高阶组件,可以在不改变原组件代码的情况下,对组件进行功能增强或者复用逻辑。开发者只需要引入高阶组件并在需要增强功能的组件上应用即可。

以下是一些高阶组件的常见应用场景:

  1. 代码复用:高阶组件可以通过提取和封装通用逻辑来实现代码复用。当多个组件需要共享相同的逻辑时,将这些逻辑提取为高阶组件,然后将这些组件作为参数传递给高阶组件,从而实现逻辑的复用。

  2. 条件渲染和授权:通过高阶组件,我们可以根据条件来控制组件的渲染。例如,我们可以创建一个需要用户登录才能访问的高阶组件,用于授权限制。

  3. 数据获取和处理:高阶组件可以用于在组件生命周期中管理和处理数据获取的逻辑。例如,我们可以创建一个高阶组件来封装数据获取的逻辑,然后将获取的数据通过props传递给包裹的组件。

  4. 功能增强:高阶组件可以用于增强组件的功能。例如,我们可以创建一个日志记录的高阶组件,用于记录组件的生命周期和操作日志。

  5. 渲染劫持:通过高阶组件,我们可以劫持组件的渲染过程,并对渲染结果进行操作。例如,我们可以创建一个高阶组件来在组件渲染前后添加一些额外的逻辑,例如loading状态的显示等。

Css3中如何使用媒体查询?响应式布局如何实现

在CSS3中,可以使用媒体查询(Media Queries)来根据设备的特性和屏幕尺寸动态地应用不同的样式。通过媒体查询,可以实现响应式布局,使网页能够适应不同的设备和屏幕尺寸。

媒体查询的语法如下:

@media mediatype and (media feature) {
 ?/* CSS 样式 */
}

其中,mediatype 表示要应用样式的媒体种类,常见的有 all (所有设备)、screen (屏幕设备)、print (打印设备)等。

media feature 是指要检查的媒体特性,比如 width (宽度)、height (高度)、orientation (方向)等。

以下是一个简单的示例,展示如何使用媒体查询来设置不同屏幕宽度下的样式:

/* 当屏幕宽度小于等于600px时应用这些样式 */
@media screen and (max-width: 600px) {
 ?body {
 ? ?background-color: red;
  }
}
?
/* 当屏幕宽度大于600px时应用这些样式 */
@media screen and (min-width: 601px) {
 ?body {
 ? ?background-color: blue;
  }
}

通过媒体查询,可以针对不同的屏幕宽度应用不同的背景颜色。当屏幕宽度小于等于600px时,背景颜色为红色;当屏幕宽度大于600px时,背景颜色为蓝色。

实现响应式布局的一种常见方法是使用媒体查询配合CSS Grid或Flexbox布局。通过设置不同屏幕尺寸下的布局和样式,可以使页面在不同设备上呈现出最佳的用户体验。

例如,以下是一个简单的响应式布局示例,使用CSS Grid布局实现:

.container {
 ?display: grid;
 ?grid-template-columns: 1fr 1fr;
}
?
@media screen and (max-width: 600px) {
 ?.container {
 ? ?grid-template-columns: 1fr;
  }
}

上述代码中,.container 是一个具有两列的网格布局。当屏幕宽度小于等于600px时,媒体查询将触发,并将网格布局改为单列。

通过媒体查询和不同的布局方式,可以根据设备的特性和屏幕尺寸来实现适应性更强的响应式布局。

Context状态树的执行流程?

在React中,Context是一种用于共享数据的机制,它允许在组件树中跨多个层级传递数据,而不必手动通过props一层层传递。Context状态树的执行流程如下:

  1. 创建Context:首先,需要使用React的createContext()方法来创建一个Context对象。例如:

const MyContext = React.createContext();
  1. 提供Context的值:在父组件中,通过将数据传递给Context的Provider组件来提供Context的值。例如:

class ParentComponent extends React.Component {
 ?render() {
 ? ?const value = 'Hello';
 ? ?return (
 ? ? ?<MyContext.Provider value={value}>
 ? ? ?  {/* 子组件 */}
 ? ? ?</MyContext.Provider>
 ?  );
  }
}

在上述代码中,将"value"作为prop传递给Provider组件,这个"value"就是Context的值。

  1. 访问Context的值:在子组件中,可以通过Context的Consumer组件来访问Context的值。例如:

class ChildComponent extends React.Component {
 ?render() {
 ? ?return (
 ? ? ?<MyContext.Consumer>
 ? ? ?  {value => <div>{value}</div>}
 ? ? ?</MyContext.Consumer>
 ?  );
  }
}

在上述代码中,通过Consumer组件的render props函数来接收Context的值,并在其内部使用。

  1. 使用Context的值:子组件可以直接使用Context的值,无论它们在组件树中的哪个位置。例如:

class GrandchildComponent extends React.Component {
 ?static contextType = MyContext;
?
 ?render() {
 ? ?const value = this.context;
 ? ?return <div>{value}</div>;
  }
}

在上述代码中,使用contextType静态属性来接收Context的值,并使用this.context来访问它。

通过这样的方式,Context的值可以在组件树中的任何地方被访问和使用,而不必手动通过props一层层传递。需要注意的是,Provider组件可以在组件树中的任何位置,而React会自动更新受影响的组件,以使其接收到新的Context值。

Redux在大型项目中目录结构你一般可以怎么划分呢?

1)actions 文件夹:存放 Redux 的 action 相关文件,每个文件通常对应一个模块或功能。可以按照功能或模块来划分子文件夹。

2)reducers 文件夹:存放 Redux 的 reducer 相关文件,也按照功能或模块进行划分。可以将相关的 reducer 放在同一个子文件夹下,并使用 combineReducers 进行合并。

3)store.js:存放 Redux store 的配置和创建逻辑。可以在此文件中导入并合并来自各个模块的 reducer,然后创建 Redux store。

4)selectors 文件夹:存放用于从 Redux store 中获取数据的 selector 函数。这些函数可以对 store 中的数据进行转换和过滤,供组件使用。

5)middleware 文件夹:存放自定义的 Redux 中间件文件。每个中间件可以有自己的文件,方便管理和维护。

6)constants 文件夹:存放 Redux 相关的常量,如 action 类型、异步请求状态等,以便在各个文件中共享和使用。

7)utils 文件夹:存放 Redux 相关的工具函数和辅助函数,如处理数据、格式化、验证等。

8)containers 文件夹:存放 Redux 的容器组件,用于连接 Redux 状态和行为到视图组件。根据页面或功能进行组织。

9)components 文件夹:存放展示型组件,不涉及 Redux 相关的逻辑。

10) hooks 文件夹:存放自定义的 React Hooks,封装对 Redux 状态和行为的访问。

文章来源:https://blog.csdn.net/kkkys_kkk/article/details/135562101
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。