前端框架——React 学习总结,这篇7000字全解决

2023-11-10

React组件复用

React组件复用:把多个组件中部分功能相似或者相同的状态或者逻辑进行复用。(复用:state和操作state的方法)。

复用的方式:

  • render props模式

  • 高阶组件(HOC)

render props模式

用children替代render(推荐)

高阶组件(HOC)

目的:实现状态逻辑复用

高阶组件(HOC,Higher-Order Components)是一个函数,接收一个要包装的组件,返回一个增强后的组件。

高阶组件内部创建一个类组件,在这个类组件中,提供复用的状态逻辑代码,通过props将复用的状态传递给被包装组件WrappedComponent

高阶组件的使用步骤

1、创建一个函数,名称以hoc开头

2、指定函数参数,参数应该以大写字母开头(作为要渲染的组件)

3、在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回该类组件。

4、在该组件中,渲染参数组件,同时将状态通过props传递给参数组件

5、调用高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中

高阶组件传递props

在改动代码:<WrappedComponent {...this.state} {...this.props}></WrappedComponent>

增加 {...this.props}

React原理

React的工作原理

1)UI = f(data){}

UI 就是界面 ,这个界面就是函数执行的结果,是按照函数式编程理念来的,我们所做的东西就是要实现这个函数,改变UI,是通过改变函数中的参数data才行的,改变data,让data来驱动这个函数,这个函数来影响(产生)UI。所以在React中,无论你实现一个组件也好,或者完成其它功能,都是要实现一个函数,改变函数中的data,让data来驱动这个函数,这个函数来影响(产生)UI,也就是说你通过改变data来改变UI,这才是React响应式的理念。

data 就是 props 和 state

开发者只需要维护可变的数据 state (what) ,让 react 框架帮助我们处理 DOM 操作(what)。

React 通过 diffing 算法计算如何更新视图。而 diffing 算法有个 的假设前提,开发人员会提供给长列表的每个子项一个 ID,帮助算法进行对比,如下图所示:

通过key保证节点的唯一性,避免了重复的渲染,可以通过上图来进行说明,React认为,如果key都相同,那么就不需要重新的计算并且渲染了,只要key不相同了(比如 新插入了一个 x 这个节点),就需要单独渲染这个 x 节点就行了。

在同一组组件中key的两个要素

1、key 在兄弟节点中是唯一的。

2、key的值是稳定的,key的值必须是固定的,不要总是改变key的值,在实际开发中,key的值不要设置数组的下标索引值,因为这样是不稳定的值,例如上图所示,之前 B的索引值是 1,但是通过改变之后,索引值就变成了 2。

3、三元表达式不需要使用key来进行标记,因为无论三元表达式的条件成立与否,都会有一个对应的值,在对应的位置进行占位。

2)完成的渲染流程

初始化的渲染流程分为 3 步。

第一步,开发者使用 JSX 语法写 React,babel 会将 JSX 编译为浏览器能识别的 React JS 语法。这一步,一般配合 webpack 在本地进行。

第二步,执行 ReactDOM.render 函数,渲染出虚拟DOM。

第三步,react 将虚拟DOM,渲染成真实的DOM。

页面更新的流程同样也是 3 步。

第一步,当页面需要更新时,通过声明式的方法,调用 setState 告诉 react什么数据变了。

第二步,react 自动调用组件的 render 方法,渲染出虚拟 DOM。

第三步,react 会通过 diffing 算法,对比当前虚拟 DOM 和需要更新的虚拟 DOM 有什么区别。然后重新渲染区别部分的真实 DOM。

什么是模块化:从 代码 的角度,去分析问题,把我们编程时候的业务逻辑,分割到不同的模块中来进行开发,这样能够方便代码的重用;

什么是组件化:从 UI 的角度,去分析问题,把一个页面,拆分为一些互不相干的小组件,随着我们项目的开发,我们手里的组件会越来越多,最后,我们如果要实现一个页面,可能直接把现有的组件拿过来进行拼接,就能快速得到一个完整的页面, 这样方便了UI元素的重用;组件是元素的集合体;

3)什么是虚拟DOM(Virtual DOM)

虚拟DOM(VDOM)是一种编程概念,是指虚拟的视图被保存在内存中,并通过诸如ReactDOM这样的库与“真实”的DOM保持同步。这个过程被称为reconciliation。

这种编程方法使用了React的声明式API:你需要告诉React你想让视图处于什么状态,React则负责确保DOM与该状态相匹配。因此你在构建你的应用时不必自己去完成属性操作、事件处理、DOM更新,React会替你完成这一切。

由于“虚拟DOM”更像一种模式而不是特定的技术,有时候我们也会用它表示其他的意思。在React的世界中,由于 “虚拟DOM” 和React元数都是用于表示视图的对象,因此常常被关联在一起。然而React也使用被称为“fibers”的对象来存放组件树的附加信息。在React中,它们也被认为是“虚拟DOM”实现的一部分。

4)影子DOM(Shadow DOM)和虚拟DOM(Virtual DOM)是相同的概念吗?

不,它们并不是相同的概念。影子DOM是一种浏览器技术,主要被设计用来为Web组件中的变量和CSS提供封装。虚拟DOM是由JavaScript库在浏览器API之上实现的一种概念。

5)Diff算法

  • tree diff:新旧DOM树,逐层对比的方式,就叫做 tree diff,每当我们从前到后,把所有层的节点对比完后,必然能够找到那些 需要被更新的元素;

  • component diff:在对比每一层的时候,组件之间的对比,叫做 component diff;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件的类型不同,则立即将旧组件移除,新建一个组件,替换到被移除的位置;

  • element diff:在组件中,每个元素之间也要进行对比,那么,元素级别的对比,叫做 element diff;

  • key:key这个属性,可以把 页面上的 DOM节点 和 虚拟DOM中的对象,做一层关联关系;

fiber是React 16中新的引擎。它的主要目的是使虚拟DOM能够进行增量渲染。

React Fiber 是对 React 核心算法的重新实现。

React Fiber 的目标是提高其对动画,布局和手势等领域的适用性。它的最重要的特性是 incremental rendering(增量渲染):它能够将渲染 work 拆分成多块并将这些任务块分散到多个帧执行。

其他的核心特性还包括当新的更新到来时暂停、中止或恢复 work 的能力;为不同类型的更新设置优先级的能力;以及新的并发原语。

6)什么是 reconciliation?

React 用来比较两棵树的算法,它确定树中的哪些部分需要被更新。

update

用来渲染 React 应用的数据的改变。通常是 setState 的结果。最终结果将是一次重新渲染React 的 API 的核心理念是将更新想象成为对整个应用的重新渲染。这允许开发者声明式地推导,而不用担心应用如何从一个状态高效的过渡到另一个状态(A 到 B,B 到 C,C 到 A 等等)。

实际上,对于每个更改重新渲染整个应用程序只适用于最简单的应用程序。在实际的应用中,对性能会有非常大的开销。

Reconciliation 是被大家广泛知晓的 "virtual DOM" 背后的算法。

  • 不同的组件类型被认为将生成本质上不同的树。React 将不尝试去进行差异比较,而是直接完全替换旧的树。

  • 对于列表的差异比较使用 key 来优化性能。Keys 应当是稳定、可预测且唯一的。

Scheduling(调度)

决定 work 何时应该被执行的过程。

work

任何计算结果都必须被执行。Work 通常是更新的结果(e.g. setState).

在 React 目前的实现中,React 递归地遍历树并且调用 render 方法在 event loop 的一次迭代中更新整棵树。不过在将来,它将延迟一些更新来防止掉帧。

这是 React 设计中一个公共的主题。一些受欢迎的库实现了“推”的方法,计算会在新数据到来的时候被执行。但是 React 坚持“拉”的方法,计算能够被推迟直到需要的时候。

React 不是一个通用的数据处理库。它只是设计来构建用户界面的库。我们认为知晓哪些计算是现在就相关的,哪些不是是在应用程序中有独一无二位置的内容。

如果一些东西在屏幕外,我们可以推迟任何与其相关的逻辑。如果数据到来的速度比帧率块,那么我们可以合并并批量更新。我们可以对来自用户与界面互动的工作(如一个按钮点击的动画)和相对不太重要的背后工作(如远程加载数据渲染新的内容)进行优先级的排序来阻止掉帧。

总结一下核心点如下:

  • 在 UI 中,并非所有的更新都需要立即生效。实际上,这样做是浪费的,可能会造成掉帧从而影响用户体验。

  • 不同类型的更新有不同的优先级。一个动画更新相比于来自数据的更新通常需要更快地被执行。

  • 一个以“推”为基础的方案要求应用程序(你,工程师)来决定如何调度工作。而一个以“拉”为核心的方案允许框架(如:React)更智能,来为你做这些决定。

iber 的主要目标是让 React 能够享受到调度带来的好处。明确地说,我们需要能够做到以下几件事:

  • 暂停任务并能够在之后恢复任务。

  • 为不同的任务设置不同的优先级。

  • 重新使用之前完成的任务。

  • 如果不在需要则可以终止一个任务。

为了做到这些事,我们首先需要一个方式来拆分这些任务为一个个任务单元。从某种意义上来说,这些任务单元就是 fiber。一个 fiber 代表了一个 任务单元.

  • 因此渲染 React 应用程序就类似于调用一个包含其他函数调用的函数。

一切皆为组件

2.1 组件

组件之间通过props 得到任何数据,都是只读的,不能重新赋值。

jsx语法中的标签,并不是直接渲染到了页面上,而是先转换成了React.createElement 这样的js代码,然后再通过render渲染到了页面中。

es6 class 类中 静态方法挂载到了constructor构造器中,实例方法挂载到了原型对象中。

react无状态组件和有状态组件的区别 无状态组件:无状态组件(Stateless Component)是最基础的组件形式,由于没有状态的影响所以就是纯静态展示的作用。一般来说,各种UI库里也是最开始会开发的组件类别。如按钮、标签、输入框等。它的基本组成结构就是属性(props)加上一个渲染函数(render)。由于不涉及到状态的更新,所以这种组件的复用性也最强。

有状态组件:在无状态组件的基础上,如果组件内部包含状态(state)且状态随着事件或者外部的消息而发生改变的时候,这就构成了有状态组件(Stateful Component)。有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。这种组件也是通常在写业务逻辑中最经常使用到的,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同。

什么时候用无状态组件?什么时候用有状态组件?

1、如果一个组件,只需要通过外界传递过来的props,渲染固定的页面,就适合使用function创建出来的无状态组件。

2、如果一个组件需要存放自己的私有数据,同时需要在组件的不同阶段执行不同的业务逻辑,就适合使用有状态组件。

在React中,我们通常通过props和state来处理两种类型的数据。props是只读的,只能由父组件设置。state在组件内定义,在组件的生命周期中可以更改。基本上,无状态组件使用props来存储数据,而有状态组件(也称为智能组件)使用state来存储数据。

总的来说:无状态函数式写法 优于React.createClass,而React.Component优于React.createClass。能用React.Component创建的组件的就尽量不用React.createClass形式创建组件。

在React中创建组件有三种方式:

  • ES5写法:React.createClass

  • ES6写法:React.Component

  • 无状态的函数写法,又称为纯组件

声明式编程

声明式与命令式的区别

  • 命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。

  • 声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。

jQuery是命令式的编程,jQuery让你去使用它的API,去做一些事情,如果jQuery的API改变了,我们写的的代码也要改变,因为API发生变化了,我们需要修改之前的API,所以这样的设计是很不友好的。

React中的写的code不大可能调用系统级别的API,相反,我们是实现一些函数,去响应,我们写的代码,只是声明我们要做什么,怎么去做,就是React来完成了,我们不用去关心,即使React的API改变了,也不会影响。

setState() 说明

  • setState() 是异步更新数据的

  • 可以多次调用setState(),但是只会触发一次render(重新渲染)

  • 推荐语法

  • setState() 的第二个参数

setState({},callback)

结论:

componentDidUpdate钩子函数的执行,提前于  this.setState执行,this.setState的第二个参数的执行效果跟componentDidUpdate钩子函数的执行效果都是一样的。

组件更新机制

5.1 setState() 两个作用

  • 修改state

  • 更新UI(组件)

5.2 组件更新过程

父组件更新时,也会更新当前父组件中所有的子组件,不会影响父组件的父组件更新,也不会影响父组件的兄弟组件更新。

5.3 避免不必要的更新渲染

组件的更新机制:父组件的更新会引起子组件的更新。

上面的问题:当子组件没有任何变化时也会进行更新。

解决办法:使用钩子函数shouldComponentUpdate(nextProps, nextState)

使用shouldComponentUpdate()可以让React知道当前状态或属性的改变是否不影响组件的输出,通过返回值决定该组件是否重新渲染,默认返回ture表示重新渲染,返回false时不会重新渲染,而且该方法并不会在初始化渲染或当使用forceUpdate()时被调用。

使用 shouldComponentUpdate(nextProps, nextState) 中的 nextState,避免不必要的更新渲染。

触发时机:更新阶段的钩子函数,组件重新渲染前执行(shouldComponentUpdate --> render)

使用 shouldComponentUpdate(nextProps, nextState) 中的 nextProps,避免不必要的更新渲染。

5.4 纯组件(PureComponent)

PureComponent中自动实现了shouldComponentUpdate钩子函数,更加方便。

PureComponent原理:纯组件内部通过分别对比props、state的值,来决定是否重新渲染组件。

纯组件内部对比的是 shallow compare(浅层对比),对于数值类型是可以,但是对于引用类型就会出现问题。

注意:props或state属性值为引用类型时,应该创建新数据,不要直接修改原数据。

同时注意:也不要使用数组的push/unshift等直接修改当前数组的方法,这些都是在修改了原数组,没有创建新的数组,应该使用concat或者slice等这些返回新数组的方法。

React路由

路由是一套映射规则,在React中,是URL路径与组件的对应关系,其实就是配置路径与组件的配对,让用户从一个视图,导航到另外一个视图中。

1、基本用法

2、编程式导航

3、默认路由

4、模糊匹配和精准匹配

在React中,React路由默认是模糊匹配模式,想要精准匹配如下所示,给默认路由添加 exact属性。

好了,所有内容分享完毕哦~记得给我点赞、分享呀~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前端框架——React 学习总结,这篇7000字全解决 的相关文章

随机推荐

  • Vue中利用计算属性computed进行模糊搜索

    data return search 模糊查询内容 tableList 从数据库获取到的列表 computed 模糊搜索 tables const search this search if search filter 方法创建一个新的数组
  • 本地缓存的几种技术及对比

    在漫长的前端开发过程中 我们常用的几种本地缓存机制 Cookie LocalStorge SessionStorge 1 Cookie的特点 1 cookie的大小受限制 cookie大小被限制在4KB 不能接受像大文件或邮件那样的大数据
  • C++笔记 16.4 模板实参推断

    primer C 笔记 模板实参推断 类型转换与模板类型参数 派生类向基类的转换不能应用于函数模板 引用形参接收数组 需要传递维度 维度也是类型的一部分 函数模板显示实参 正常类型转换应用于显示指定的实参 尾置返回类型与类型转换 进行类型转
  • 前端VUE渗透测试的一些技巧和思路

    Webpack是一个前端资源加载 打包工具 它将根据模块的依赖关系进行静态分析 然后将这些模块按照指定的规则生成对应的静态资源 但一般情况下所有打包的文件都会被加载 导致了泄露一些敏感信息 如敏感的path api接口等 案例一 未授权泄露
  • java oracle 插入_oracle 连接java 并且用java向数据库数插入数据------在dept表格中 插入 新的部门编号 部门名称 部门位置...

    package oracledemo import java sql import java util Scanner import javax sql public class moxie0926 param args public st
  • 二叉树常见的问题和解决思路

    文章目录 整体思路 一 判断是否为AVL 二 判断是否对称 三 判断是否为BST 四 各种遍历 五 将二叉树进行中心对称反转 六 求某种遍历顺序中的倒数第k个节点 七 求二叉树的节点个数 八 求二叉树的层数 九 搜索BST中指定区间的元素
  • Java中String类的isEmpty方法、null以及""的区别

    一直以来对String的这三个空挺晕的 刚好同事问我 我也学习下 从别人博客上看到的是这样的 isEmpty 分配了内存空间 值为空 是绝对的空 是一种有值 值 空 分配了内存空间 值为空字符串 是相对的空 是一种有值 值 空字串 null
  • 交换两个变量的值+int*[]与int(*)[]的辨析

    交换两个变量的值 不使用第三个变量 即 a 3 b 5 交换之后 a 5 b 3 有两种解法 一种用算术算法 一种用 异或 a a b b a b a a b or a a b 只能对 int char b a b a a b or a b
  • 这个效果是怎么做的?

    http higkoo i sohu com blog view 81445953 htm 想要那个红狐狸效果
  • 【论文阅读】MPViT : Multi-Path Vision Transformer for Dense Prediction

    发表年份 2021 12 发表单位 Electronics and Telecommunications Research Institute ETRI South Korea 期刊 会议 CVPR 论文链接 https arxiv org
  • Servlet_01_介绍

    Servlet的作用是处理请求 服务器会把接收到的请求交给Servlet来处理 在Servlet中通常需要 1 接收请求数据 2 处理请求 3 完成响应 例如客户端发出登录请求 或者输出注册请求 这些请求都应该由Servlet来完成处理 S
  • ubuntu下学习c++(输出定义变量)

    2022 6 11 学习cout cin的使用方法以及变量的定义 include
  • 接口和类有啥区别:

    接口和类有啥区别 接口是一系列抽象方法的集合 接口中只有抽象方法 只有的意思就是 没有成员变量 除了静态常量 没有构造方法 因此不能被实例化 类只是一种抽象的数据类型 接口没有构造方法 一个类只能继承一个类 但是可以实现多个接口 接口中不能
  • 远处是风景,近处是人生

    常听到有人说 最近好累 想出去走走 换个地方透透气 如果去到大理 心情一定如花儿一般灿烂 如果去到内蒙 心情一定如草原一般辽阔 如果去到三亚 心情一定如大海一般坦荡 但实际上 改变你心情的从不是新的城市或者美丽的景色 是你愿意与生活和解的态
  • 网络常考题

    45 当数据接收者不能处理更多数据时 哪一层发出停止信息给发送者 A 网络层 B 传输层 C 会话层 D 表示层 B 49 在传输层采用了以下哪些方法来保证接收缓冲区不溢出 多选 A 数据分段 B 确认机制 C 流量控制 D 滑动窗口 E
  • Spring中@JsonFormat与@DateTimeFormat注解使用简介说明

    转自 Spring中 JsonFormat与 DateTimeFormat注解使用简介说明 下文笔者讲述Spring中JsonFormat和DateTimeFormat注解的简介说明 如下所示 JsonFormat和DateTimeForm
  • C语言编译执行的全过程

    编译 编译程序读取源程序 字符流 对之进行词法和语法的分析 将高级语言指令转换为功能等效的汇编代码 再由汇编程序转换为机器语言 并且按照操作系统对可执行文件格式的要求链接生成可执行程序 C源程序头文件 gt 预编译处理 cpp gt 编译程
  • 高光谱遥感数值建模技术及在植被、水体、土壤信息提取领域应用

    在高光谱影像中 结合纹理 表面粒度 风化程度 作物密度等辅助信息 能估计出多种地物及其上覆作物的状态参量 提高遥感高定量分析的精度和可靠性 如何通过构建遥感光谱反射信号与地表参数之间的关系模型来实现数值计算 是举办本次培训班的主要目的 针对
  • 校园网络系统服务器配置摘要,校园网网络应用服务器配置

    浅谈校园网网络应用服务器配置 摘要 以某校园网为例 在网络应用服务器设计这个环节中 我们分别用到了web服务器 ftp服务器 dns服务器 dhcp服务器 mail服务器 并且在一台已经安装了windows 2003 server的计算机上
  • 前端框架——React 学习总结,这篇7000字全解决

    React组件复用 React组件复用 把多个组件中部分功能相似或者相同的状态或者逻辑进行复用 复用 state和操作state的方法 复用的方式 render props模式 高阶组件 HOC render props模式 用childr