【React】精选10题

1.React Hooks带来了什么便利?

React Hooks是React16.8版本中引入的新特性,它带来了许多便利。

  1. 更简单的状态管理
    使用useState Hook可以在函数组件中方便地管理状态,避免了使用类组件时需要继承React.Component的繁琐操作。

  2. 避免使用类组件:函数式组件的书写方式更加简单、直观,避免了类组件中this指针的混乱问题。

  3. 更少的重复代码:使用useEffect Hook可以方便地实现数据获取、DOM操作等副作用相关的操作,避免了在不同的生命周期函数中重复编写相似的代码。

  4. 更好的代码复用:自定义Hook可以将一些可复用的逻辑封装起来,方便在不同的组件中复用。

  5. 更好的逻辑分离:使用useContext、useReducer和自定义Hook等可以帮助将逻辑分离到独立的模块中,提高代码的可维护性和可扩展性。

总之,React Hooks带来了更加简单、直观、高效的编程方式,可以让开发者更加专注于组件的逻辑实现。使得React的函数组件也具备了类组件的一些特性。

2. 列举几个常见的 Hook?

  1. useState Hook:用于在函数组件中管理状态,可以通过调用useState Hook来声明一个状态变量和更新函数,例如:

    const [count, setCount] = useState(0);
    
  2. useEffect Hook:用于在函数组件中处理副作用,可以传入一个回调函数和一个依赖数组,例如:

    useEffect(() => {// 处理副作用
    }, [dependency]);
    
  3. useContext Hook:用于在函数组件中访问React Context中的值,例如:

3.1. 在MyContext.js中定义MyContext上下文对象:

import { createContext } from 'react';const MyContext = createContext();
export default MyContext;

3.2. 在App.js中使用MyContext.Provider包裹Child组件,传递要共享的数据

import MyContext from './MyContext';
import Child from './Child';function App() {const data = 'hello world';return (<MyContext.Provider value={data}><Child /></MyContext.Provider>);
}

3.3 在Child.js中使用useContext函数获取到MyContext传递的值:

import MyContext from './MyContext';function Child() {const data = useContext(MyContext);return <h1>{data}</h1>;
}export default Child;
  1. useReducer Hook:用于在函数组件中管理复杂状态,可以将一个reducer函数和初始状态传入useReducer Hook,返回一个状态和派发更新的函数,例如:
import React, { useReducer } from 'react';const initialState = { count: 0 };function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}
}function Counter() {const [state, dispatch] = useReducer(reducer, initialState);return (<div>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button></div>);
}
  1. useCallback Hook:用于在函数组件中缓存回调函数,避免因为每次渲染都重新创建回调函数导致子组件重复渲染,例如:
import React, { useState, useCallback } from 'react';function MyComponent() {const [count, setCount] = useState(0);const handleClick = useCallback(() => {setCount(count + 1);}, [count]);return (<div><p>Count: {count}</p><button onClick={handleClick}>Increment Count</button></div>);
}

在这个示例中,我们使用了 useCallback Hook 缓存了 handleClick 函数。handleClick 会在点击按钮时被调用,并将 count 的值加 1。我们将 count 作为依赖数组传入 useCallback 中,确保每次 count 发生变化时,handleClick 函数都会被更新。

使用 useCallback Hook 可以避免在每次渲染时都创建新的函数引用,从而提高性能。这对于传递给子组件的回调函数尤其有用,确保子组件不会不必要地重新渲染。同时,也可以使用 useMemo Hook 缓存计算结果,从而进一步提高性能。

  1. useMemo Hook:提供的一个 Hook,用于缓存计算结果,避免在每次渲染时都重新计算,从而提高性能。它接收一个计算函数和一个依赖数组作为参数,返回缓存的计算结果。
    例如:
import React, { useMemo, useState } from 'react';function MyComponent() {const [count, setCount] = useState(0);const expensiveCalculation = useMemo(() => {console.log('Calculating...');let result = 0;for (let i = 0; i < count * 1000000; i++) {result += i;}return result;}, [count]);return (<div><p>Count: {count}</p><p>Expensive Calculation: {expensiveCalculation}</p><button onClick={() => setCount(count + 1)}>Increment Count</button></div>);
}
  1. useRef: 获取组件的真实节点或存储一些不常更新的数据,这些数据不受组件重新渲染影响。
  • 获取真实节点
const ref = useRef(null)
<div ref ={ref} > </div>
// 设置真实节点属性 .current为固定用法
ref.current.style.color = 'red'
  • 存储数据
const ref_obj = useRef({name:'icy',age:23
})
// 改变存储的数据
ref.obj.current.name = 'icy-godlike'

还有其他常用的Hook函数,如useImperativeHandle、useLayoutEffect等,开发者可以根据具体的需求选择不同的Hook函数。

3. 使用React Hooks有什么优势?

简化组件的复杂度:React Hooks可以帮助组件更加简洁明了,避免类组件中的一些复杂的生命周期函数。

更容易共享逻辑:React Hooks可以将组件中的状态和逻辑提取出来,通过自定义Hook在不同的组件中进行共享。

更容易测试:React Hooks可以将状态和逻辑的处理分离,使得测试变得更容易。

更好的性能:React Hooks可以避免类组件中因为响应式更新造成的额外渲染,从而提高应用的性能。

更快的开发速度:React Hooks能够帮助开发者更快地构建出复杂的UI组件,从而提高开发效率。

4. 简单介绍下React中diff算法?

在 React 中,当组件的状态发生变化时,React 会重新渲染组件。为了提高渲染效率,React 会使用一种叫做 diff 算法(也称为协调算法)来计算出哪些部分需要更新,哪些部分不需要更新。

简单来说,diff 算法就是比较两棵树的差异,然后将差异应用到真实的 DOM 树上,从而实现只更新必要的部分,避免全量更新。

React 中的 diff 算法具体实现如下:

对比两棵树的根节点,如果类型不同,则直接替换整个节点及其子节点,不再进行进一步比较;如果类型相同,则进入下一步。

对比节点的属性,如果发生变化,则更新节点的属性;如果没有变化,则进入下一步。

对比子节点,React 使用一种叫做 key 的机制来判断哪些节点需要更新,哪些节点需要删除,哪些节点需要新增。如果节点的 key 相同,则认为是同一节点,进行进一步比较;如果节点的 key 不同,则直接替换整个节点及其子节点,不再进行进一步比较。

对比完成后,React 会根据计算出的差异,生成一份更新计划(也称为变更记录),然后根据这份更新计划,进行 DOM 操作,将变更应用到真实的 DOM 树上。

通过使用 diff 算法,React 可以避免全量更新,从而提高渲染效率,使得 React 在大规模数据渲染的场景下仍然能够保持流畅的性能。

5. React中,能否直接将 props 的值复制给 state?

可以,但是应该避免这种写法:

constructor(props) {super(props);// 不要这样做this.state = { color: props.color };
}

只有在初始化组件状态时才能这样做。在组件的生命周期中,props 的值是不会自动更新到 state 中的,因此如果需要在组件运行时更新 state,需要使用setState()方法。

6. React Hooks当中的useEffect是如何区分生命周期钩子的

useEffect 钩子函数可以接收两个参数,第一个参数是一个函数,称为 effect 函数,第二个参数是一个数组,称为依赖项数组。

在 React 中,每一个组件都有不同的生命周期钩子,例如 componentDidMount,componentDidUpdate,componentWillUnmount 等。useEffect 钩子函数可以在一个函数中处理这些不同的生命周期钩子。

当使用 useEffect 钩子函数时,React 会自动根据参数来判断当前需要使用哪个生命周期钩子。

当依赖项数组为空时,useEffect 钩子函数的行为类似于 componentDidMount 和 componentWillUnmount 的结合体,即只在组件挂载时执行一次,并在组件卸载时执行清理操作。

当依赖项数组不为空时,useEffect 钩子函数的行为类似于 componentDidUpdate,即在组件挂载时执行一次,之后每次依赖项发生变化时都会执行一次,最后在组件卸载时执行清理操作。

因此,useEffect 钩子函数的行为会根据传入的依赖项数组的变化而变化,从而实现了不同的生命周期钩子的功能。

useEffect(() => {console.log('mounted'); // 依赖数组为[]时,componentDidMount | 依赖数组不为空,且发生变化时 componentDidUpdatereturn () => {console.log('willUnmount'); //  依赖数组为[]时,componentWillUnmount }}, [source]);

7. 为什么不能用数组下标来作为react组件中的key?

在 React 中,key 属性用于标识组件在列表中的顺序,并用于优化组件的重新渲染。key 必须是唯一的,并且在组件列表中始终保持不变。

不能使用数组下标作为 key 属性是因为数组下标与组件的实际内容没有关系。例如,如果你在一个列表中删除第一个元素,React 将重新生成列表中所有元素的 key,因为数组下标已经改变,导致 React 需要重新渲染所有组件。

此外,使用数组下标作为 key 属性可能会导致错误的渲染结果。例如,如果你有两个组件,它们的 key 属性分别为 0 和 1,并且你想交换它们的顺序,则交换它们在数组中的位置可能会导致 key 属性被错误地匹配到错误的组件上,从而导致渲染错误。

因此,为了避免以上问题,key 属性应该是与组件的实际内容相关的唯一标识符,例如组件在数据库或服务端的 ID。

8. React Fiber是什么?

React Fiber 是 React 16 中引入的新的协调引擎。React Fiber 是一种新的、可中断的调度算法,可以更好地支持渐进式渲染、处理大型组件树以及优化代码的可维护性。

React Fiber 的主要目标是提高 React 应用程序的性能和交互性。具体来说,React Fiber 可以:

实现异步渲染,将渲染任务分割成多个小任务,并调度它们的执行顺序,以提高应用程序的响应性和流畅性。
支持可中断的渲染,允许 React 在执行长时间的计算或等待异步数据时中断渲染,并在后台执行其他任务,以避免应用程序的停顿或卡顿。
支持渐进式渲染,允许 React 逐步地将组件树渲染到屏幕上,从而更快地响应用户输入,并提高应用程序的交互性。
改进错误处理和调试功能,使得开发人员可以更轻松地调试和修复错误。
总之,React Fiber 是 React 16 中的一个重要特性,可以显著提高 React 应用程序的性能、交互性和可维护性。

9. 虚拟DOM一定更快吗?

虚拟 DOM 并不一定比直接操作 DOM 更快,因为在生成虚拟 DOM 的过程中也需要进行计算和操作。但是,使用虚拟 DOM 有以下几个优点:

减少不必要的操作:由于 React 使用了虚拟 DOM,可以将多次 DOM 操作合并为一次,从而减少了不必要的 DOM 操作,提高了性能。
避免重复渲染:React 会比较新旧虚拟 DOM 树的差异,只更新差异部分对应的真实 DOM,避免了重复渲染整个组件,提高了性能。
跨平台支持:虚拟 DOM 是 React 在 Web、Native 等多个平台都可以使用的重要原因之一。
当然,在某些场景下,直接操作 DOM 也可能比使用虚拟 DOM 更快,例如非常简单的组件或需要频繁更新的组件。但总的来说,在大多数情况下,使用虚拟 DOM 可以提高 React 应用程序的性能和可维护性。

10. 不同版本的 React 都做过哪些优化?

React 16 引入了 Fiber 架构,以提高应用程序的性能和交互性。
React 16.3 引入了新的 Context API,以更方便地共享数据和状态。
React 16.6 引入了 memo 和 lazy 函数,以更有效地处理组件性能和代码分离。
React 16.8 引入了 Hooks,以更方便地处理组件之间的状态和逻辑。
React 17 引入了新的事件系统以及一些其他的优化,例如对异常的处理方式等等。
除此之外,React 还对一些其他的细节进行了优化,例如对组件生命周期方法的改进、对 Virtual DOM 的优化、对 React Native 的优化等等。

React渲染页面的两个阶段:

调度阶段(reconciliation):在这个阶段 React 会更新数据生成新的 Virtual DOM,然后通过Diff算法,快速找出需要更新的元素,放到更新队列中去,得到新的更新队列。
渲染阶段(commit):这个阶段 React 会遍历更新队列,将其所有的变更一次性更新到DOM上。

React 15 架构

React15架构可以分为两层:

Reconciler(协调器)—— 负责找出变化的组件;
Renderer(渲染器)—— 负责将变化的组件渲染到页面上;
在React15及以前,Reconciler采用递归的方式创建虚拟DOM,递归过程是不能中断的。如果组件树的层级很深,递归会占用线程很多时间,递归更新时间超过了16ms,用户交互就会卡顿。

为了解决这个问题,React16将递归的无法中断的更新重构为异步的可中断更新,由于曾经用于递归的虚拟DOM数据结构已经无法满足需要。于是,全新的Fiber架构应运而生。

React 16 架构

为了解决同步更新长时间占用线程导致页面卡顿的问题,也为了探索运行时优化的更多可能,React开始重构并一直持续至今。重构的目标是实现Concurrent Mode(并发模式)。

从v15到v16,React团队花了两年时间将源码架构中的Stack Reconciler重构为Fiber Reconciler。

React16架构可以分为三层:

Scheduler(调度器)—— 调度任务的优先级,高优任务优先进入Reconciler;
Reconciler(协调器)—— 负责找出变化的组件:更新工作从递归变成了可以中断的循环过程。Reconciler内部采用了Fiber的架构;
Renderer(渲染器)—— 负责将变化的组件渲染到页面上。

React 17 优化

React16的expirationTimes模型只能区分是否>=expirationTimes决定节点是否更新。React17的lanes模型可以选定一个更新区间,并且动态的向区间中增减优先级,可以处理更细粒度的更新。

Lane用二进制位表示任务的优先级,方便优先级的计算(位运算),不同优先级占用不同位置的“赛道”,而且存在批的概念,优先级越低,“赛道”越多。高优先级打断低优先级,新建的任务需要赋予什么优先级等问题都是Lane所要解决的问题。

Concurrent Mode的目的是实现一套可中断/恢复的更新机制。其由两部分组成:

一套协程架构:Fiber Reconciler
基于协程架构的启发式更新算法:控制协程架构工作方式的算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/37692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小红书运营 变现方法总结(精)

大家好&#xff0c;我是网媒智星&#xff0c;今天跟大家分享一下小红书运营方面的知识&#xff0c;怎样利用小红书变现&#xff1f;全篇倾情干货输出&#xff0c;认真学习&#xff0c;保证您收获多多。 首先&#xff0c;让我们来分析一下小红书平台的优势。关于卖东西&#xff…

Open3D (C++) 基于拟合高差的点云地面点提取

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、原始点云2、提取结果四、相关链接系列文章(连载中。。。): Open3D (C++) 基于高程的点云地面点提取Open3D (C++) 基于拟合平面的点云地面点提取Open3D (C++) 基于拟合高差的点云地面点提取</

vue + less 实现动态主题换肤功能

文章目录 前言一、前提条件1. 初始化vue项目2. 安装插件 二、新建文件夹主题theme1.style.less文件2.model.js文件3.theme.js文件theme文件夹最终效果 三、修改vue.config.js文件四、页面上的具体使用1. index.vue 页面2. index.vue 页面注意点说明3. index.vue 效果 五、在js中…

VSCode使用SSH无密码连接Ubuntu

VSCode使用SSH无密码连接Ubuntu 前提条件&#xff1a; 1. 能够正常使用vscode的Remote-ssh连接Ubuntu 2. Ubuntu配置静态ip&#xff08;否则经常需要修改Remote-ssh的配置文件里的IP&#xff09; 链接-> ubuntun 18.04设为静态ip&#xff08;.net模式&#xff0c;可连接…

shell使用总结

一、语法 数据类型 字符串 如果没有特殊说明&#xff0c;数据类型默认都是字符串。常见字符串操作有&#xff1a; 已知变量strabcabc 1、切片 echo ${str:1:3} #${varName:offset:size},分页取子串 echo ${str:2} #${varName:offset},偏移offset个字符取至末端 echo …

加载AB包程序集,反射获取并实例化类调用方法

加载AB包文件&#xff0c;加载bytes程序集资源&#xff0c;通过反射获取类&#xff0c;实例化添加组件&#xff0c;调用方法 public class LoadAB : MonoBehaviour {private void Update(){if (Input.GetKeyDown(KeyCode.H)){Load();}}void Load(){string classname "ID…

如何解决docker中出现的“bash: vim: command not found”

目录 问题描述&#xff1a; 问题解决&#xff1a; 问题描述&#xff1a; 在docker中&#xff0c;想要执行vim编辑文件&#xff0c;弹出“docker bash: vim: command not found“&#xff08;如下图&#xff09;&#xff0c;请问该如何解决&#xff1f; 问题解决&#xff1a; …

FPGA应用学习笔记------系统复位一(同异复位)

要满足复位恢复时间才能正常复位&#xff0c;不然会产生输出准稳态&#xff0c;输出逻辑错误 复位恢复时间只会存在复位释放时刻&#xff0c;不会出现在确立时刻&#xff0c;则不推荐完全异步复位 完全同步复位&#xff0c;肯定是同步于时钟滴&#xff0c;并将总是满足时钟条件…

研发工程师玩转Kubernetes——就绪探针(Readiness Probe)和服务(Service)

在《研发工程师玩转Kubernetes——启动、存活和就绪探针》中&#xff0c;我们讲了就绪探针和服务之间的特殊关系。就绪探针检测失败并不代表整个程序处于“非存活”状态&#xff0c;可能只是短暂临时的不可以提供服务&#xff0c;比如CPU阶段性占满&#xff0c;导致就绪探针检测…

【Spring MVC】Spring MVC基于注解的程序开发

目录 一、什么是Spring MVC 二、Spring MVC项目的创建和使用 1、实现客户端和服务器端之间的连接 1.1、RequsestMapping注解 1.2、RequestMapper的简单使用 1.3、使用GetMapping和POSTMapping注解来实现HTTP连接 三、获取参数 1、实现获取单个参数 2、实现获取对象 3…

解决ubantu驱动掉了的问题

这里写自定义目录标题 解决ubuntu驱动掉了的问题 解决ubuntu驱动掉了的问题 首先确定是否有驱动&#xff1a; ls /usr/src | grep nvidia若有&#xff0c;则大概率是驱动版本与内核版本对应不上&#xff0c;则把内核版本切换为初始版本即可。参照&#xff1a;https://blog.cs…

书写自动智慧:探索Python文本分类器的开发与应用:支持二分类、多分类、多标签分类、多层级分类和Kmeans聚类

书写自动智慧&#xff1a;探索Python文本分类器的开发与应用&#xff1a;支持二分类、多分类、多标签分类、多层级分类和Kmeans聚类 文本分类器&#xff0c;提供多种文本分类和聚类算法&#xff0c;支持句子和文档级的文本分类任务&#xff0c;支持二分类、多分类、多标签分类…

nodejs+vue+elementui+express智慧社区小区物业管理系统的设计与实现_2p760

开发语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;VScode 前端nodejsvueelementuiexpress vue的文件结构其实就是一个index.html 中间的内容&#xff0c;用的是vue&#xff0c;但最终都会转…

OpenCV图像处理——形态学操作

目录 连通性形态学操作腐蚀和膨胀开闭运算礼帽和黑帽 连通性 形态学操作 形态学转换是基于图像形状的一些简单操作。它通常在二进制图像上执行。腐蚀和膨胀时两个基本的形态学运算符。然后它的变体形式如开运算&#xff0c;闭运算&#xff0c;礼帽黑帽等 腐蚀和膨胀 cv.erode…

费曼学习法

费曼学习法 费曼学习法&#xff08;Feynman Technique&#xff09;是一种学习和理解复杂概念的方法&#xff0c;以理查德费曼&#xff08;Richard Feynman&#xff09;这位著名的理论物理学家命名。该方法的核心思想是通过将学习内容简化并用自己的话解释给别人&#xff0c;来…

Node.js学习笔记-04

这第九章也是个大重点 九、玩转进程 Node在选型时决定在V8引擎之上构建&#xff0c;也就意味着它的模型与浏览器类似。 本章关于进程的介绍和讨论将会解决如下两个问题&#xff1a; 单进程单线程并非完美&#xff0c;如今CPU基本均是多核的&#xff0c;真正的服务器&#xf…

背上小书包准备面试之TypeScript篇

目录 typescript是啥&#xff1f;与javascript的区别&#xff1f; typescript数据类型&#xff1f; typescript中枚举类型&#xff1f;应用场景&#xff1f; typescript中接口的理解&#xff1f;应用场景&#xff1f; typescript中泛型的理解&#xff1f;应用场景&#xf…

轻薄的ESL电子标签有哪些特性?

在智慧物联逐渐走进千万家的当下&#xff0c;技术变革更加日新月异。ESL电子标签作为科技物联的重要组成部分&#xff0c;是推动千行百业数字化转型的重要技术&#xff0c;促进物联网产业的蓬勃发展。在智慧零售、智慧办公、智慧仓储等领域&#xff0c;ESL电子标签在未来是不可…

win11右下角图标(网络,音量,电量)点击无反应问题,两分钟解决!

win11系统用的好好的&#xff0c;突然有一天任务栏右下角的常用三件套&#xff08;网络&#xff0c;音量&#xff0c;电量&#xff09;左键单击没反应&#xff0c;无法方便的调节音量和连接wifi&#xff0c;如下图所示&#xff0c;但是右键好用&#xff0c;不过不方便。网上查了…

嵌入式 C 语言程序数据基本存储结构

一、5大内存分区 内存分成5个区&#xff0c;它们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 1、栈区(stack)&#xff1a;FIFO就是那些由编译器在需要的时候分配&#xff0c;在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。 ​…