《一》React 基础

基于 React18。

React 是 Facebook 开发的一个用于构建用户界面的 JavaScript 库。

React 的特点:

  1. 声明式编程:React 采用声明式编码,指的是我们只需要维护自己的状态 state,当状态改变时,React 会自动执行 render 函数,根据最新的状态去渲染 UI 界面。

    命令式编程:命令机器如何去做事情(how),这样不管想要的是什么(what),它都会按照你的命令实现。
    声明式编程:告诉机器想要的是什么(what),让机器想出如何去做(how)。
    例如:想让一个数组里的数值翻倍。

    // 命令式编程:需要先遍历整个数组,取出每个元素,乘以二,然后把翻倍后的值放入新数组,一步一步都要告诉程序
    var numbers = [1,2,3,4,5]
    var doubledNumbers = []
    for(var i = 0; i < numbers.length; i++) {
    	var newNumber = numbers[i] * 2
    	doubledNumbers.push (newNumber)
    }
    
    // 声明式编程:只需要告诉程序想要数组里的数值翻倍
    var numbers = [1,2,3,4,5]
    var doubledNumbers = numbers.map(n => n * 2)
    
  2. 组件化开发:React 采用组件化开发,指的是将复杂的页面拆分成一个个小的组件,然后再将这些组件组合、嵌套在一起,最终形成应用程序。
  3. 一次学习,跨平台编写:例如在 React Native 中就可以使用 React 语法进行移动端开发。

使用 React:

在现有网站中添加 React:

  1. 在 HTML 中准备一个容器。
  2. 添加依赖。
    • 引入 react 核心库:react 包中包含了 react web 和 react native 所共同拥有的核心代码。引入之后就会有一个全局对象 React。
    • 引入 react-dom 扩展库: react-dom 包针对 web 和 native 所做的事情不同。在 web 端,react-dom 包最终会将 JSX 渲染成真实 DOM,显示在浏览器中;在 native 端,react-dom 包最终会将 JSX 渲染成原生的空控件(例如: Android 中的 Button,IOS 中的 UIButton 等)。因此将 react-dom 包单独拆分了出来。引入之后就会有一个全局对象 ReactDOM。
    • 引入 babel:用于将 JSX 转为 JS,以便在浏览器中运行。
  3. 编写 React 代码。
<body>
	<!-- 准备一个容器 -->
	<div id="root"></div>

	<!-- 添加依赖 -->
	<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
	<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
	<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
	
	<!-- 编写 React 代码:React18 之前 -->
	<script type="text/babel" > //  type="text/babel" 是为了让 babel 知道它需要解析来解析这段 JSX
		ReactDOM.render(<h1>Hello,React</h1> , document.getElementById('root')) // 将要显示的内容渲染到根元素中。第一个参数是一个 HTML 元素或 React 组件,第二个参数是要渲染到的页面中的元素
	</script>

	<!-- 编写 React 代码:React18 之后 -->
	<script type="text/babel" > //  type="text/babel" 是为了让 babel 知道它需要解析来解析这段 JSX
		const root = ReactDOM.createRoot(document.getElementById('root')) // 创建一个根元素。参数是要渲染到的页面中的元素
		root.render(<h1>Hello,React</h1> ) // 将要显示的内容渲染到根元素中。参数是一个 HTML 元素或 React 组件
	</script>
</body>

请添加图片描述

基于 React 脚手架 create-react-app 创建一个新的 React 项目:

传统的脚手架:指的是在搭建建筑物时临时搭建出来的一个框架。
请添加图片描述
编程中的脚手架:是一种可以帮助开发者快速生成项目的工程化结构的工具。脚手架让项目从搭建到开发,再到部署,整个流程变得快速和便捷。

  1. 全局安装 create-react-app 脚手架(简称 cra):npm i create-react-app -g

    安装成功后,可以通过 create-react-app --version 可以查看 create-react-app 的版本。

  2. 切换到想要创建项目的目录,创建基于 React 脚手架的项目:create-react-app react-demo

    项目名称不能包含大写字母。

  3. 进入项目所在的目录: cd react-demo
  4. 开启项目并且会自动打开浏览器:npm start

    npm run start:会打开一个本地的服务器,并且将项目托管在这个服务器中,就可以在本地浏览网站。
    npm run build :在 build 文件夹内生成应用的优化版本,build 文件夹中的文件可以被用于部署到生产环境。
    npm run ejectcreate-react-app 脚手架是基于 Webpack 开发的,但是在生成的项目目录中并没有看到 Webpack 相关的内容,这是因为 create-react-app 脚手架将 Webpack 相关的配置隐藏了。通过 npm run eject 可以将 Webpack 配置信息弹出。这个操作是不可逆的,要谨慎使用。

使用 create-react-app 架手架创建出来的项目默认目录结构:

请添加图片描述

  1. node_modules:项目依赖的第三方包。
  2. public:网站的静态资源文件和 项目的 HTML 入口文件。
  3. src:网站的源代码,是基于 ES6 标准的 React 代码。

    基于 ES6 标准的 React 代码是不能直接被浏览器执行的,因此 src 和 public 文件夹中所有的代码和资源都要转化成可以被浏览器识别的基于 ES5 标准的 JavaScript 代码,这些转化后的代码将会被打包统一放置在一个新生成的 build 文件夹中。

  4. build:可以被浏览器执行的 ES5 标准的 JavaScript 代码。
  5. .gitignore:git 的忽略文件。
  6. package.json:记录项目的基础信息、依赖包版本信息等。
  7. package-lock.json:记录 node_modules 目录下所有包的名称、版本号、下载地址以及当前包又依赖了哪些包等。
  8. README.md:项目的说明文档。

React 的渲染机制:

请添加图片描述

  1. render() 方法中会返回 JSX,JSX 会被转换成 React.createElement() 函数的调用。
  2. React.createElement() 会创建出来一个 ReactElement(React 元素),ReactElement 是一个虚拟节点,其实就是一个 JS 对象。
  3. React 利用 ReactElement 组成一个 JS 的对象树,也就是虚拟 Dom。
  4. 最终,React 根据虚拟 Dom 渲染出真实 Dom (document.createElement()),呈现在页面中。
// JSX
const element = (
	<div className='header'>
		<div>标题</div>
	</div>
)	

// JSX 本质上是 React.createElement()
const element = React.createElement(
	"div", 
	{
	  className: "header"
	},
	React.createElement("div", null, "标题")
)
// 虚拟 DOM 节点
console.log(element)

请添加图片描述

// 真实 DOM 节点
<div class='header'>
	<div>标题</div>
</div>
const dom = document.getElementsByClassName('header')[0]
console.log(dom)

请添加图片描述

React 的更新机制:

请添加图片描述

React 中的虚拟 Dom:

虚拟 Dom:ReactElement 组成的对象树,其实就是由一堆 JS 对象来模拟真实的 Dom 结构。

React 中虚拟 Dom 的作用:

  1. 通过虚拟 Dom 和 Diff 算法可以实现视图的高效更新:
    • 在 React 中,所有的 Dom 构造都是通过虚拟 Dom 进行,而不总是直接操作页面真实 Dom,虚拟 Dom 是内存数据,性能极高。
    • 每当数据变化时,React 都会重新构建整个完整的 Dom 树,然后 React 将当前整个 Dom 树和上一次的 Dom 树进行对比,得到 Dom 结构的区别,然后仅仅将需要变化的部分进行实际的浏览器 DOMDom更新,而且 React 能够批量处理虚拟 Dom 的刷新。

    在 Web 开发中,总需要将变化的数据实时反应到 UI 上,这时就需要对 Dom 进行操作,而复杂或频繁的 Dom 操作通常是性能瓶颈产生的原因。

  2. 通过虚拟 Dom 可以实现跨平台:虚拟 Dom 本质上就是一堆 JS 对象,因此React 既可以将它渲染成 Web 端的 HTML 元素,也可以通过桥接的方式将它渲染成移动端(IOS、Android)的控件。
  3. 虚拟 Dom 帮助开发者从命令式编程转到了声明式编程的模式:UI 以一种虚拟化的方式存在于内存中,开发者只需要维护状态,然后告诉 React 希望 UI 是什么状态,React 就能够确保 Dom 和状态是匹配的。

React 中的 Diff 算法:

传统的 Diff 算法是通过循环递归的方式对 Dom 节点进行依次的比对,效率较低,其复杂度可达到 O(n^3),其中 n 代表的节点个数。那么如果有 1000 个节点,则一次 Diff 就将进行 10 亿次比较。

React 中使用三个层级策略对传统的 Diff 算法进行了优化,使复杂度从 O(n^3) 降到了 O(n)。

React 是基于组件构建的,首先可以将整个虚拟 DOM 树抽象为 React 组件树,每一个组件又是由一棵更小的组件树构成,依次类推。将 React diff 策略应用比较这棵组件树,若其中某个组件需要进行比较,将这个组件看成一棵更小的组件树,继续用 React diff 策略比较这棵更小的组件树,依次类推,直到层次遍历完所有的需要比较的组件。

tree diff:

树层级的比较:React 只对同层级的节点进行比较,不考虑节点的跨层级比较,如果发生跨级操作,React 不复用已有节点。
在这里插入图片描述
React 只会对相同颜色框内的节点进行比较,如此只需要遍历一次虚拟 Dom 树,就可以完成整个的对比。
在这里插入图片描述
B 节点发生了跨层级的移动操作,React 并不会复用 B 节点及其子节点,而是会直接删除 A 节点下的 B 节点及其子节点,然后再在 C 节点下创建新的 B 节点及其子节点。

component diff:

组件的比较:如果是同类型的组件,就按照 React diff 策略进行比较;如果不是同类型的组件,React 不会进行比较,而是直接替换这个组件及其子孙节点。

对于同类型组件, React 通过让开发人员自定义 shouldComponentUpdate() 方法来进行比较优化,减少组件不必要的比较。如果没有自定义,shouldComponentUpdate() 方法默认返回 true,每次组件发生数据(state & props)变化时,都会进行比较。

在这里插入图片描述
虽然组件 C 和组件 H 结构相似,但类型不同,React 不会进行比较,会直接删除组件 C,创建组件 H。

element diff:

单个节点的比较:可以通过对同一层级的单个节点设置唯一的 key 来复用已有的节点。

对于同一层级的单个节点,有三种操作,分别是移动、创建和删除,针对是否使用 key 标识可分为两种情况:

  1. 对于不使用 key 标识的情况:
    在这里插入图片描述
    React 对同一层级的新旧单个节点进行对比,发现新集合中的 B 不等于旧集合中的 A,于是删除 A,创建 B,依此类推,直到删除 D,创建 C。这会使得相同的节点不能复用,出现频繁的删除和创建操作,从而影响性能。
  2. 对于使用 key 标识的情况:
    在这里插入图片描述
    React 会对新集合进行遍历,通过唯一的 key 来判断旧集合中是否存在相同的节点,如果没有则创建,如果有则判断是否需要进行移动操作。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值