react 基础语法

前置知识

类的回顾

  • 通过class关键字定义一个类
  • 类名首字母大写
  • class类有constructor构造器
  • new 一个类得到一个实例
  • 类还有方法,该方法也会在其原型上
  • static静态数据,访问静态属性通过 类名.id
  • getter和setter
    • getter:定义一个属性,必须返回一个值,通过 实例.属性 去进行访问,相当于Vue中的computed即计算属性。在 react 的类组件中计算属性就是 getter 的写法
    • setter:属性,可以通过该属性去修改值

class Animal {static id = 1;constructor(name){this.name = name;}getName() {return this.name;}//getter获取类的名字get computedName() {return this.name + Animal.id;}// setterset computedName(name){this.name = name;}
}console.log(Animal.id); // 1let animal = new Animal('zs');
console.log(animal); // zs
console.log(animal.getName()); // zs
console.log(animal.computedName); // zs1
animal.computedName = 'ls';
console.log(animal.name); // ls
console.log(animal.computedName); // ls1
  • 类的继承通过 extends、super
    • 子类可以继承父类,子类就会拥有父类的方法和属性等,同时子类也可以重写父类的方法和定义属于自己的属性和方法
class Animal {static id = 1;constructor(name){this.name = name;}getName() {return this.name;}//getter获取类的名字get computedName() {return this.name + Animal.id;}// setterset computedName(name){this.name = name;}
}class Dog extends Animal {constructor(name){super(name)}getName(){return this.name + '123'}
}let dog = new Dog('泰迪');
console.log(dog.name); // 泰迪
console.log(dog.getName()); // 泰迪 -- >泰迪123
dog.computedName = '柯基';
console.log(dog.computedName);// 柯基1
console.log(dog.computedName);// 柯基1

this 指向

  • 在普通函数中,this指向window,如果是严格模式,则指向undefined
  • 在类的构造函数中,this指向实例对象
  • 在对象的方法里,this指向调用这个方法的对象
  • 箭头函数中的this指向外层(父级)
  • 改变this指向:call、apply、bind
    • call:改变this指向后会立即执行;直接传参
    • apply:改变this指向后会立即执行;通过数组传参
    • bind:改变this指向后不会立即执行,而是返回一个函数,需手动调用;直接传参

示例1:

const obj = {name: 'zs',getName(){return this.name}
}const obj1 = {name: 'ls'
}console.log(obj.name); // zs
console.log(obj.getName()); // zs
console.log(obj.getName.call(obj1)); // ls
console.log(obj.getName.apply(obj1)); // ls
console.log(obj.getName.bind(obj1)()); // lsconst obj = {name: 'zs',getName(num,age){return this.name + num + age}
}const obj1 = {name: 'ls'
}console.log(obj.name); // zs
console.log(obj.getName()); // zs
console.log(obj.getName.call(obj1, 2,6)); // ls26
console.log(obj.getName.apply(obj1, [5,0])); // ls50
console.log(obj.getName.bind(obj1)(3,18)); // ls318

示例2:

function Cat() {let showName = function () {console.log(1);}return this;
}Cat.showName = function(){console.log(2);
}Cat.prototype.showName = function(){console.log(3);
}var showName = function () {console.log(4);
}function showName() {console.log(5);
}Cat.showName(); // 2 访问的是函数的静态属性
showName(); // 4 函数优先提升,var变量提升后赋值将原来的函数覆盖掉了
Cat().showName(); // 4 Cat()函数返回了this指向的是window,全局var定义的变量是在window上的
new Cat.showName(); // 2 new 实例化的是Cat里面的静态属性 showName 
new Cat().showName(); // 3 实例化的是 Cat 实例,访问的是cat实例的方法showName()

React 概述

  • 官网地址:React 官方中文文档
  • 目前前端最流行的是三大框架:Vue、React、Angular

React 简介

react是一个用于构建用户界面的 JavaScript 库

react官网(React)

react中文网(React 官方中文文档)

  • React 是一个用于构建用户界面(UI,对咱们前端来说,简单理解为:HTML 页面)的 JavaScript 库
  • Vue 是一个渐进式的 JavaScript 框架
  • 如果从mvc的角度来看,React仅仅是视图层(V)的解决方案。也就是只负责视图的渲染,并非提供了完整了M和C的功能
  • react/react-dom/react-router/redux: 框架
  • React 起源于 Facebook 内部项目(News Feed,2011),后又用来架设 Instagram 的网站(2012),并于 2013 年 5 月开源react介绍
  • React 是最流行的前端开发框架之一,其他:Vue、Angular 等等框架对比

react特点

声明式UI:

你只需要描述UI(HTML)看起来是什么样的,就跟写HTML一样

const jsx = <div className="app"><h1>Hello React! 动态数据变化:{count}</h1>
</div>

声明式对应的是命令式,声明式关注的是what,命令式关注的是how

组件化开发:

  • 组件是react中最重要的内容
  • 组件用于表示页面中的部分内容
  • 组合、复用多个组件,就可以实现完整的页面功能

学习一次,随处使用(多平台适配):

  • 使用react/rect-dom可以开发Web应用
  • 使用react/react-native可以开发移动端原生应用(react-native)  RN   安卓 和 ios应用,    flutter也可以做到
  • 使用react可以开发VR(虚拟现实)应用(react360)

 

总结:

  • 声明式设计,react采用声明范式,能够轻松的描述应用
  • 高效 :react提供了虚拟DOM,最大程度地减少了与DOM之间的交互
  • 灵活:react可以和任意的库进行搭配使用

虚拟DOM

在 react 中每个DOM对象都会有一个对应的虚拟DOM,以js对象的方式描述的真实的DOM对象

<div className="container"><h3>12</h3><p>45</p>
</div>{type: 'div',props: { className: 'container' },children: [{type: 'h3',props: null,children: [{type: 'text',props: {textContent" '12'},}]
},{type: 'p',props: null,children: [{type: 'text',props: {textContent" '45'},}]}]
}

虚拟DOM如何提升效率:

  • 精准找出发生变化的DOM,只更新变化的部分
  • 在第一次创建DOM时,就会给每个DOM对象创建虚拟DOM,更新时就会更新虚DOM,然后将更新的前后的虚拟DOM进行对比,从而找到发生变化的部分,将发生变化的部分更新到真实的DOM对象中,从而达到性能提升

React 使用方式

原始方式使用

使用 react 必须要包含以下几个包:

  • react:react核心包
  • react-dom:与操作DOM相关功能的核心包
  • (babel)babel-standalone:由babel编译器提供的js文件,可以将es6代码转换成es5代码
  • babeljs官网:Babel 中文文档 | Babel中文网 · Babel 中文文档 | Babel中文网
  • jsx最终会转换成React.createElement的方式去创建模板,jsx只是降低了开发难度

引入方式:

  1. CDN方式
  1. 直接下载到本地在引入
  1. 通过 npm 进行管理(脚手架创建)

基本示例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./node_modules/react/umd/react.production.min.js"></script><script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script><script src="./node_modules/babel-standalone/babel.min.js"></script>
</head>
<body><div id="root"></div><script>let template = React.createElement('h1', null, 'hello react');let template2 = React.createElement('h2', null, 'hello react2')let template3 = React.createElement('h3', null, 'hello react3');let container = React.createElement('div', null, [template, template2, template3]);// react18之前ReactDOM.render(template, document.getElementById('root'));// react18之后// const root = ReactDOM.createRoot(document.getElementById('root'));// root.render(template2);</script>
</body>
</html>

React.createElement:创建react模板

ReactDOM.render:将模板渲染到哪个标签上去

优化示例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./node_modules/react/umd/react.production.min.js"></script><script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script><script src="./node_modules/babel-standalone/babel.min.js"></script>
</head>
<body><div id="root"></div><script type="text/babel">let message = 'hello world';function handlerMsg(){meaashe = 'hello world2';// 在react中修改后默认不会重新自动渲染界面rootRender();}// react18之前ReactDOM.render(rootRender(), document.getElementById('root'));// react18之后// const root = ReactDOM.createRoot(document.getElementById('root'));// root.render(rootRender());// 创建多个(18以后)// const root = ReactDOM.createRoot(document.getElementById('app'));// root.render(rootRender())function rootRender() {const container = (<div><h1>hello</h1><h2>hello2</h2><h3 onClick={handlerMsg}>{message}</h3></div>);}// rootRender();</script>
</body>
</html>

通过对比,我们发现jsx的写法比上面写法更加的直观,层次结构更加清晰,写法更简单

组件化示例

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./node_modules/react/umd/react.production.min.js"></script><script src="./node_modules/react-dom/umd/react-dom.production.min.js"></script><script src="./node_modules/babel-standalone/babel.min.js"></script>
</head>
<body><div id="root"></div><script type="text/babel">// 类组件class App extends React.Component {// 数据constructor() {super()this.state = {message: "hello world"}// this绑定this.handlerMsg = this.handlerMsg.bind(this)}// 方法handlerMsg(){this.setState({message: 'hello world2',})}// 渲染render() {const { message } = this.state;return {<div>// <h3 onClick={this.handlerMsg.bind(this)}>{message}</h3> // this绑定<h3 onClick={this.handlerMsg}>{message}</h3></div>}}}// react18之前ReactDOM.render(<App/>, document.getElementById('root'));// react18之后// const root = ReactDOM.createRoot(document.getElementById('root'));// root.render(<App/>);// 创建多个(18以后)// const root = ReactDOM.createRoot(document.getElementById('app'));// root.render(<App/>)</script>
</body>
</html>

基本步骤

  • 使用步骤
- 导入react和react-dom     
- 创建react元素(虚拟DOM)
- 渲染react元素到页面中

  • 导入react和react-dom
// 导入react和react-dom
import React from 'react'
import ReactDOM from 'react-dom'

  • 创建react元素
// 创建元素
const title = React.createElement('h1', null, 'hello react')

  • 渲染react元素到页面
// 渲染react元素
ReactDOM.render(title, document.getElementById('root'))

脚手架方式使用

React 脚手架的介绍
  • 脚手架:为了保证各施工过程顺利进行而搭设的工作平台
  • 对于前端项目开发来说,脚手架是为了保证前端项目开发过程顺利进行而搭设的开发平台
  • 脚手架的意义:
    • 现代的前端开发日趋成熟,需要依赖于各种工具,比如,webpack、babel、eslint、sass/less/postcss等
    • 工具配置繁琐、重复,各项目之间的配置大同小异
    • 开发阶段、项目发布,配置不同
      • 项目开始前,帮你搭好架子,省去繁琐的 webpack 配置
      • 项目开发时,热更新、格式化代码、git 提交时自动校验代码格式等
      • 项目发布时,一键自动打包,包括:代码压缩、优化、按需加载等

使用 React 脚手架创建项目
  • 首先确保已经安装了 nodejs
  • 其次 npm 版本要大于 5.2
  • 然后通过 npm 安装 npm i -g create-react-app
    • create-react-app --version 检测安装的版本
    • create-react-app 项目名称 安装react项目;需要注意的是在创建react项目给项目命名的时候不允许有大写字母
  • 或者直接通过以下命令:npx create-react-app react-basic(项目名称),创建react项目   npx create-react-app react-demo --template typescript
    • npx create-react-app 是固定命令,create-react-app 是 React 脚手架的名称
    • react-basic 表示项目名称,可以修改
    • npm create vite@latest my-react-app -- --template react-ts,参考地址:https://cn.vitejs.dev/guide/
    • 安装好react项目后可以运行以下命令:npm i prettier eslint-config-prettier esli nt-plugin-prettier --save-dev  来安装 prettier 和 eslint 来进行管理代码,安装完成后需要做以下配置:
// .eslinttrc.js
"extends": ["plugin:prettier/recommended" // 新增,并且在 vscode 里安装 prettier 插件
]// 在 package.json 文件里,新增以下代码,并且运行 npm format
"scripts": {"format": " prettier --write 'src/**/*.+(js|ts|jsx|tsx)' "
},// 在项目根目录下新建 .vscode 目录,在该目录下新建 settings.json
// 目的就是告诉vscode在我保存文件的时候就去帮我自动运行 npm format,而不用自己每次都去手动运行{"editor.codeActionsOnSave": {"source.fixAll.eslint": true,}}// 在项目根目录下新建 .prettierrc.js 进行配置自己的一些规则
module.exports = {// 箭头函数只有一个参数的时候可以忽略括号arrowParens: 'avoid',// 括号内部不要出现空格bracketSpacing: true,// 行结束符使用 Unix 格式endOfLine: 'lf',// true: Put > on the last line instead of at a new linejsxBracketSameLine: false,// 行宽printWidth: 100,// 换行方式proseWrap: 'preserve',// 分号semi: false,// 使用单引号singleQuote: true,// 缩进tabWidth: 2,// 使用 tab 缩进useTabs: false,// 后置逗号,多行对象、数组在最后一行增加逗号trailingComma: 'es5',parser: 'typescript',
}
  • 启动项目:yarn start or npm start
  • npx 是 npm v5.2 版本新添加的命令,用来简化 npm 中工具包的使用
    • 原始:1 全局安装npm i -g create-react-app 2 再通过脚手架的命令来创建 React 项目
    • 现在:npx 调用最新的 create-react-app 直接创建 React 项目

 

项目目录结构说明和调整
  • README.md:说明文档
  • package.json:对整个应用程序的描述,包括:应用名称、版本号、一些依赖包、以及项目的启动、打包等
  • public
    • favicon.ico:应用程序顶部的icon图标
    • index.html:相当于html模板文件,react最终会将模板挂载到html中的div元素上即应用程序的入口文件
    • logo192.png:被在mainfest.json中使用
    • logo512.png:被在mainfest.json中使用
    • mainfest.json:和 web app 配置相关
    • robots.txt:指定搜索引擎可以或者无法爬取哪些文件
  • src
    • assets:存放一些静态资源,比如css、图片等
    • components:存放项目中的一些自定义组件
    • App.css:App组件相关的样式
    • App.js:项目的根组件,相当于vue中的app.vue
    • App.test.js:App组件的测试代码文件
    • Index.css:全局样式文件
    • index.js:项目的入口文件,相当于vue中的main.js
    • logo.svg:启动项目所看到的图标
    • reportWebVitals.js:
    • setupTests.js:测试初始化文件
  • npm run start:启动项目,开服
  • npm run build:项目打包生产包
  • npm run eject:项目中的一些配置被隐藏起来了,通过这个命令可以将配置文件反编译到项目中,从而获得配置的权利,这个操作是不可逆的,一旦编译出来就无法编译回去,一般来说不会执行这个命令,我们会通过其他方式去修改配置。
  • 说明:
    • src 目录是我们写代码进行项目开发的目录
    • 查看 package.json 两个核心库:reactreact-dom(脚手架已经帮我们安装好,我们直接用即可)
  • 调整(参考):
    1. 删除 src 目录下的所有文件
    2. 创建 index.js 文件作为项目的入口文件,在这个文件中写 React 代码即可

PWA

  • PWA全称 Progressive Web App,即渐进式WEB应用
  • 一个PWA应用首先的一个网页,可以通过Web技术编写出一个网页应用
  • 随后添加上App Manifest和Service Worker来实现PWA安装和离线等功能
  • 这种Web存在的形式,我们称之为Web App

PWA解决了哪些问题:

  • 可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏
  • 实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能
  • 实现了消息推送
  • 等等一系列类似于 Native App 相关的功能

安装调试工具

方式1

  1. 打开github获取到插件项目,并现在到本地。
    插件的地址为:https://github.com/facebook/react-devtools/tree/v3,从这个地址里面找到DownloadZIP,将项目现在到本地。

  1. 解压项目,并安装依赖。
    下载的zip文件解压到本地的目类里面。接着进入react-devtools-3目录,在控制台使用npm install命令将当前工程的依赖现在到本地。
  1. 指定命令打包生成插件
    再进入到react-devtools-3\shells\chrome切换到chrome目录下,运行node build.js,当前目录下会生成build目录 这个build目录下的unpacked目录就是chrome中所需react-devtools的工具扩展程序包。

  1. 打开chrome浏览器,配置插件
    打开谷歌浏览器,网址输入chrome://extensions/,选择加载已解压的程序,选择我们上一步生成的unpacked文件夹,这样就把插件安装成功。


这个时候你在chrome加载插件栏里面就可以看到React Developer Tools插件。
接着我们运行代码,就可以在浏览器中选择react来查看组件。

方式2

克隆代码到本地

git clone https://github.com/facebook/react-devtools.git

切换到v3分支

git checkout -b v3 origin/v3

安装依赖

yarn

进入shells\chrome下

node build

在谷歌浏览器的扩展程序中添加shells\chrome\build\unpacked文件夹

方式3

如果可以访问外网的话,可以在谷歌浏览器的谷歌商店里直接进行下载安装即可

 

VSCode代码片段配置

我们在前面练习React的过程中,有些代码片段是需要经常写的,我们在VSCode中我们可以生成一个代码片段,方便我们快速生成

VSCode中的代码片段有固定的格式,所以我们一般会借助于一个在线工具来完成

具体的步骤如下

 第一步,复制自己需要生成代码片段的代码;

 第二步,https://snippet-generator.app/在该网站中生成代码片段;

 第三步,在VSCode中配置代码片段;

 

JSX语法

时下虽然接入 JSX 语法的框架(React、Vue)越来越多,但与之缘分最深的毫无疑问仍然是 React。2013 年,当 React 带着 JSX 横空出世时,社区曾对 JSX 有过不少的争议,但如今,越来越多的人面对 JSX 都要说上一句“真香”!典型的“真香”系列。

什么是 JSX

  • JSX 是一个 JavaScript 的语法扩展,类似于模板语法,或者说是一个类似于 XML 的 ECMAScript 语法扩展,并且具备 JavaScript 的全部功能。
  • 网络标签语言有两种,HTML、XML
  • HTML:是网页的布局,更多的用语内容的呈现
  • XML:可扩展的标签原因,可以写任意的标签,核心功能是用于数据的传输
  • JSX=JavaScript+XML,是JavaScript和XML的结合,可以说是JavaScript的一种扩展语法,可以在jsx中写js代码,也可以写html中DOM元素,在jsx中拥有js的所有的语法。
  • 不同于Vue中的模块语法,无需去专门学习模块语法的一些指令,比如v-for、v-if、v-else、v-bind...
  • 与javascript的语法很接近

使用jsx语法的特点:

  • jsx执行更快,因为它在编译成JavaScript代码后进行了优化
  • jsx是类型安全的,在编译过程中就可以发现错误,可以防止注入攻击
  • 使用jsx编写代码更加的简单快捷
  • 只能有一个根元素

JSX的基本使用

JSX 语法是如何在 JavaScript 中生效的?

React

在 React 框架中,JSX 的语法是如何在 JavaScript 中生效的呢?React 官网给出的解释是,JSX 会被编译为 React.createElement(), React.createElement() 将返回一个叫作“React Element”的 JS 对象

对于 JSX 的编译是由 Babel 来完成的。

Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

当然 Babel 也具备将 JSX 转换为 JS 的能力

其实如果仔细看,发现 JSX 更像是一种语法糖,通过类似模板语法的描述方式,描述函数对象。

其实在 React 中并不会强制使用 JSX 语法,我们也可以使用 React.createElement 函数

在采用 JSX 之后,这段代码会这样写:

通过对比发现,在实际功能效果一致的前提下,JSX 代码层次分明、嵌套关系清晰;而 React.createElement 代码则给人一种非常混乱的“杂糅感”,这样的代码不仅读起来不友好,写起来也费劲。

JSX 语法写出来的代码更为的简洁,而且代码结构层次更加的清晰。

JSX 语法糖允许我们开发人员像写 HTML 一样来写我们的 JS 代码。在降低学习成本的同时还提升了我们的研发效率和研发体验。

Vue

当然在 Vue 框架中也不例外的可以使用 JSX 语法,虽然 Vue 默认推荐的还是模板。

为什么默认推荐的模板语法,引用一段 Vue 官网的原话如下:

任何合乎规范的 HTML 都是合法的 Vue 模板,这也带来了一些特有的优势:

  • 对于很多习惯了 HTML 的开发者来说,模板比起 JSX 读写起来更自然。这里当然有主观偏好的成分,但如果这种区别会导致开发效率的提升,那么它就有客观的价值存在。
  • 基于 HTML 的模板使得将已有的应用逐步迁移到 Vue 更为容易。
  • 这也使得设计师和新人开发者更容易理解和参与到项目中。
  • 你甚至可以使用其他模板预处理器,比如 Pug 来书写 Vue 的模板。

有些开发者认为模板意味着需要学习额外的 DSL (Domain-Specific Language 领域特定语言) 才能进行开发——我们认为这种区别是比较肤浅的。首先,JSX 并不是没有学习成本的——它是基于 JS 之上的一套额外语法。同时,正如同熟悉 JS 的人学习 JSX 会很容易一样,熟悉 HTML 的人学习 Vue 的模板语法也是很容易的。最后,DSL 的存在使得我们可以让开发者用更少的代码做更多的事,比如 v-on 的各种修饰符,在 JSX 中实现对应的功能会需要多得多的代码。

更抽象一点来看,我们可以把组件区分为两类:一类是偏视图表现的 (presentational),一类则是偏逻辑的 (logical)。我们推荐在前者中使用模板,在后者中使用 JSX 或渲染函数。这两类组件的比例会根据应用类型的不同有所变化,但整体来说我们发现表现类的组件远远多于逻辑类组件。

例如有这样一段模板语法。

使用 JSX 语法会写成这样。

转换为 createElement 转换的 JS 就变成了这样。

但是不管是模板语法还是 JSX 语法,都不会得到浏览器纯天然的支持,这些语法最后都会被编译成相应的 h 函数(createElement函数,不泛指所有版本,在不同版本有差异)最后变成 JS 对象,这里的编译也是和 React 一样使用的 Babel 插件来完成的。

不管是 React 推崇的 JSX 语法,还是 Vue 默认的模板语法,目的都是为了让我们写出来的代码更为的简洁,而且代码接口层次更加的清晰。在降低学习成本的同时还提升了我们的研发效率和研发体验。

读到这里,相信你已经充分理解了“JSX 是 JavaScript 的一种语法扩展,它和模板语言很接近,并且具备 JavaScript 的全部功能。”这一定义背后的深意。

不管是 React 还是 Vue 我们都提到了一个函数 createElement,这个函数就是将我们的 JSX 映射为 DOM的。

JSX 是如何映射为 DOM 的:起底 createElement 源码

对于 creatElement 源码的分析,我们也分 React 和 Vue 来为大家解读。

源码分析的具体版本没有必要去过于详细的讨论,因为不管是 React 还是 Vue 对于在实现 createElement 上在不同版本差别不大。

React:

createElement 函数有 3 个入参,这 3 个入参包含了我们在创建一个 React 元素的全部信息。

  • type:用于标识节点的类型。可以是原生态的 div 、span 这样的 HTML 标签,也可以是 React 组件,还可以是 React fragment(空元素)。
  • config:一个对象,组件所有的属性(不包含默认的一些属性)都会以键值对的形式存储在 config 对象中。
  • children:泛指第二个参数后的所有参数,它记录的是组件标签之间嵌套的内容,也就是所谓的“子节点”“子元素”。

从源码角度来看,createElement 函数就是将开发时研发人员写的数据、属性、参数做一层格式化,转化为 React 好理解的参数,然后交付给 ReactElement 来实现元素创建。

接下来我们来看看 ReactElement 函数

源码异常的简单,也就是对 createElement 函数转换的参数,在进行一次处理,包装进 element 对象中返给开发者。如果你试过将这个返回 ReactElement 进行输出,你会发现有没有很熟悉的感觉,没错,这就是我们老生常谈的「虚拟 DOM」,JavaScript 对象对 DOM 的描述。

最后通过 ReactDOM.render 方法将虚拟DOM 渲染到指定的容器里面。

Vue:

vue2

我们在来看看 Vue 是如何映射 DOM 的。

createElement 函数就是对 _createElement 函数的一个封装,它允许传入的参数更加灵活,在处理这些参数后,调用真正创建 VNode 的函数 _createElement:

_createElement 方法有 5 个参数:

  • context 表示 VNode 的上下文环境。
  • tag 表示标签,它可以是一个字符串,也可以是一个 Component。
  • data 表示 VNode 的数据。
  • children 表示当前 VNode 的子节点,它是任意类型的,它接下来需要被规范为标准的 VNode 数组。
  • normalizationType 表示子节点规范的类型,类型不同规范的方法也就不一样,它主要是参考 render 函数是编译生成的还是用户手写的。

_createElement 实现内容略多,这里就不详细分析了,反正最后都会创建一个 VNode ,每个 VNode 有 children,children 每个元素也是一个 VNode,这样就形成了一个 VNode Tree,它很好的描述了我们的 DOM Tree。

当 VNode 创建好之后,就下来就是把 VNode 渲染成一个真实的 DOM 并渲染出来。这个过程是通过 vm._update 完成的。Vue 的 _update 是实例的一个私有方法,它被调用的时机有 2 个,一个是首次渲染,一个是数据更新的时候,我们这里只看首次渲染;当调用 _update 时,核心就是调用 vm.patch 方法。

patch::这个方法实际上在不同的平台,比如 web 和 weex 上的定义是不一样的

引入一段代码来看看具体实现。

在 vm._update 的方法里是这么调用 patch 方法的:

首次渲染:

  • $el 对应的就是 id 为 app 的 DOM 元素。
  • vnode 对应的是 render 函数通过 createElement 函数创建的 虚拟 DOM。
  • hydrating 在非服务端渲染情况下为 false。

确认首次渲染的参数之后,我们再来看看 patch 的执行过程。一段又臭又长的源码。

在首次渲染时,由于我们传入的 oldVnode( id 为 app 的 DOM 元素 ) 实际上是一个 DOM container,接下来又通过 emptyNodeAt 方法把 oldVnode 转换成 VNode 对象,然后再调用 createElm 方法,通过虚拟节点创建真实的 DOM 并插入到它的父节点中。

通过起底 React 和 Vue 的 createElement 源码,分析了 JSX 是如何映射为真实 DOM 的,实现思路的整体方向都是一样的。所以说优秀的框架大家都在相互借鉴,相互学习。

总结
  • React 的设计初衷是「关注点分离」,React 本身的关注基本单位是组件,在组件内部高内聚,组件之间低耦合。而模板语法做不到。并且 JSX 并不会引入太多的新的概念。 也可以看出 React 代码更简洁,更具有可读性,更贴近 HTML。
  • 通过对比多种方案,发现 JSX 本身具备他独享的优势,JSX 语法写出来的代码更为的简洁,而且代码结构层次更加的清晰。JSX 语法糖允许我们开发人员像写 HTML 一样来写我们的 JS 代码。在降低学习成本的同时还提升了我们的研发效率和研发体验。
  • 并且JSX 本身没有太多的语法,也不期待引入更多的标准。实际上,在 16 年的时候,JSX 公布过 2.0 的建设计划与小部分新特性,但很快被 Facebook 放弃掉了。整个计划在公布不到两个月的时间里便停掉了。其中一个原因是 JSX 的设计初衷,即并不希望引入太多的标准,也不期望 JSX 加入浏览器或者 ECMAScript 标准。

createElement的问题

  • 繁琐不简洁
  • 不直观,无法一眼看出所描述的结构
  • 不优雅,开发体验不好

 

类组件:

App.js

import ClassHello from './components/classHello'function App() {return (<div className="App"><ClassHello /></div>);
}export default App;

classHello.jsx

import React, { Component } from 'react'export default class classHello extends Component {// 定义变量constructor(props){super(props)this.state = {message: 'hello'}}// 方法--更改变量handlerMsg = () => {this.setState({message: 'hello react'})}// 渲染函数render() {return (<div><p>{this.state.message}</p><button onClick={this.handlerMsg}>更改</button></div>)}
}

JSX注意点

  • 只有在脚手架中才能使用jsx语法
    • 因为JSX需要经过babel的编译处理,才能在浏览器中使用。脚手架中已经默认有了这个配置。
  • JSX必须要有一个根节点, <></>  <React.Fragment></React.Fragment>,只有一个根节点
  • JSX可以是单标签页可以是双标签,单标签节点的元素需要使用/>结束
  • JSX中语法更接近与JavaScript
    • class =====> className
    • for========>  htmlFor
  • JSX可以换行,如果JSX有多行,推荐使用()包裹JSX,防止自动插入分号的bug
import React, { PureComponent } from 'react'export default class demoClassComponent extends PureComponent {constructor() {super()this.state = {}}render() {return (<div><p></p></div>)}
}

使用prettier插件格式化react代码:

  • 安装插件

  • 添加prettier的配置
// 保存到额时候用使用prettier进行格式化
"editor.formatOnSave": true,
// 不要有分号
"prettier.semi": false,
// 使用单引号
"prettier.singleQuote": true,
// 默认使用prittier作为格式化工具
"editor.defaultFormatter": "esbenp.prettier-vscode",

嵌入JavaScript语句

在jsx中可以在{}来使用插入js表达式

在jsx中,要嵌入js表达式,使用单花括号{}, 那么也就意味着在单花括号中可以写js表达式

let title = '我是标题';function App() {return (<div>{title}</div>);
}export default App;

JSX嵌入变量作为子元素:

  • 当变量是Number、String、Array类型时,可以直接使用
  • 当变量是null、Boolean、undefined类型时,内容为空。如果希望可以显示null、Boolean、undefined,那么需要转换成字符串,可以利用toString、空字符串拼接的方式等
  • Object类型不能直接作为子元素,会报错 Objects are not valid as a React,可以通过
<p>{obj.message}</p>
<p>{Objct.keys(obj)[0]}</p>
...

嵌入算数表达式

可以在jsx嵌入表达式中写算数表达式,包括加减乘除

let num1 = 1;
let num2 = 2;function App() {return (<div>{num1 + num2}</div>);
}export default App;

嵌入条件表达式

在jsx的嵌入表达式中,条件判断语句只能写三目运算符,不能写if/else、switch/case条件判断语句,一旦写上条件判断语句后会报错

let age = 18function App() {return (<div>{age >= 18 ? '成年' : '未成年'}</div>);
}export default App;

嵌入函数表达式

在jsx中可以将函数直接运行。

let age = 17function isAdult() {if (age >= 18) {return '成年'} else {return '未成年'}
}function App() {return (<div>{isAdult()}</div>);
}export default App;

嵌入对象表达式

实例1

let user = {name: '张三',age: 20
}function App() {return (<div>{user}</div>);
}export default App;

在jsx嵌入表达式中直接渲染对象数据会报错,报错如下:

正确方式应该将对象中的每个数据进行渲染,而不是渲染整个对象:

let user = {name: '张三',age: 20
}function App() {return (<div>姓名:{user.name}<br />年龄:{user.age}</div>);
}
export default App;

实例2

import React, { Component } from "react";export default class demo extends Component {constructor(props) {super(props);this.state = {message: "welcome",obj: {name: "zs",age: 14,},};}handleMsg = () => {this.setState({message: "welcome to react18",});};render() {return (<div><p>姓名:{this.state.obj.name}</p><p>年龄:{this.state.obj.age}</p><p>{this.state.message}</p><button onClick={this.handleMsg}>更改</button></div>);}
}

嵌入数组表达式

数组有点特殊,可以直接放入进行渲染,通常在元素中循环渲染一个数组,用.map,相当于vue中的v-for

实例1(推荐写法)

// let students = [<p>张三</p>, <p>李四</p>, <p>王五</p>];
let students = ['张三', '李四', '王五']function App() {return (<div>{students.map(item => {return <p key={item}>{item}</p>})}</div>);
}export default App;

实例2

你也可以用其他方式去实现:

// let students = [<p>张三</p>, <p>李四</p>, <p>王五</p>];
let students = ['张三', '李四', '王五']function getStudents() {let res = [];students.forEach(item => {res.push(<p key={item}>{item}</p>);});return res;
}function App() {return (<div>{getStudents()}</div>);
}export default App;

但是,我们推荐使用.map方式

实例3

import React, { Component } from "react";export default class demo extends Component {constructor(props) {super(props);this.state = {array: ["张三", "李四", "王五"],array2: [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' },{ id: 3, name: 'Item 3' }]};}// 方式一handleArrayInfo = () => {// setState 方法只能用于更新对象中的属性,而不能直接更新数组中的某个元素const newArray = [...this.state.array]; // 创建一个新的数组newArray[0] = "星期二";this.state.array = newArray;this.forceUpdate(); // 强制重新渲染组件};// 方式二updateArrayItem = (id, newName) => {// 复制原数组const newArray = [...this.state.array2];// 查找要更新的元素索引const index = newArray.findIndex(item => item.id === id);// 更新元素的属性值if (index !== -1) {newArray[index].name = newName;// 使用 setState 更新组件状态this.setState({ array2: newArray });}};render() {return (<div><div>{this.state.array.map((item) => {return <p key={item}>{item}</p>;})}</div><button onClick={this.handleArrayInfo}>更改值</button><div>{this.state.array2.map((item) => {return <p key={item.id}>{item.name}</p>;})}</div><button onClick={() => this.updateArrayItem(2, 'New Item 2')}>Update Item 2</button></div>);}
}

防止注入攻击

let str = "<p>我是p标签</p>"let value = {__html: str
}function App() {return (<div dangerouslySetInnerHTML={value}></div>);
}export default App;

在jsx中,字符串里面的标签不会被解析成真实的DOM元素,而是当做字符串进行渲染,如果你要将字符串中的标签解析成真实的DOM元素,你需要创建一个对象

let value = {__html: str
}

其中__html字段是固定的

创建完毕后,需要在元素上给一个属性dangerouslySetInnerHTML去进行解析

JSX中的注释

{/* 这是jsx中的注释 */}   推荐快键键 ctrl + /
  • 不要出现语句,比如if for
<div className='color bg-color'>{/* {title} */}
</div>

JSX中的属性绑定

  • 比如元素会有 title 属性
  • 比如 img 元素的 src属性
  • 比如 a 元素的 href 属性
  • 比如元素的 class(className) 属性或者是 style 属性
  • ......
import React, { PureComponent } from 'react'export default class demoClassComponent extends PureComponent {constructor() {super()this.state = {title: 'hello world',imgUrl: 'https://xxxx',alttitle: '图片',hrefUrl: 'https://www.baidu.com/',isActive: true,}}render() {const { title, imgUrl, alttitle, hrefUrl, isActive } = this.stateconst className = `adc vdc ${isActive ? 'active1' : ''}`const classList = ['adc', 'fvb']if (isActive) classList.push('active2')return (<div><h2 title={title}>{title}</h2><img src={imgUrl} alt={alttitle} /><a href={hrefUrl}>百度一下</a>{/* 动态class */}<p className={`abc cba ${isActive ? 'active' : ''}`}>我是p标签</p><p className={className}>我是p1标签</p><p className={classList.join(' ')}>我是p2标签</p>{/* 动态style */}<p style={{ color: 'red', fontSize: '30px' }}>哈哈哈</p></div>)}
}

条件渲染

在react中,一切都是javascript,所以条件渲染完全是通过js来控制的

if/else

  • 通过判断if/else控制
const isLoding = false
const loadData = () => {if (isLoding) {return <div>数据加载中.....</div>} else {return <div>数据加载完成,此处显示加载后的数据</div>}
}const title = <div>条件渲染:{loadData()}</div>

三元运算符

  • 通过三元运算符控制
const isLoding = false
const loadData = () => {return isLoding ? (<div>数据加载中.....</div>) : (<div>数据加载完成,此处显示加载后的数据</div>)
}

逻辑运算符

  • 逻辑运算符
const isLoding = false
const loadData = () => {return isLoding && <div>加载中...</div>
}const title = <div>条件渲染:{loadData()}</div>
# 应用场景:当某个值有可能为 undefined 时,使用 && 进行条件判断

模拟v-show

  • 模拟v-show
import React, { Component } from 'react';class classHello extends Component {constructor(){super()this.state = {msg: 'hello',isShow: true}}changeShow = () => {this.setState({isShow: !this.state.isShow})}render() {const {isShow, msg} = this.statereturn (<div><h3>类组件</h3><button onClick={() => this.changeShow()}>切换</button><div>{isShow && <h2>{msg}</h2>}<p style={{display: isShow ? 'block' : 'none'}}>123</p></div></div>);}
}export default classHello;

vscode配置自动补全:

// 当按tab键的时候,会自动提示
"emmet.triggerExpansionOnTab": true,
"emmet.showAbbreviationSuggestions": true,
// jsx的提示
"emmet.includeLanguages": {"javascript": "javascriptreact"
}

列表渲染

我们经常需要遍历一个数组来重复渲染一段结构

在react中,通过map方法进行列表的渲染

for循环

  • for循环
const songs = ['温柔', '倔强', '私奔到月球']
const songItems = []
for(let i = 0; i < songs.length; i++){const movie = songs[i]const liEl = <li>{movie}</li>songItems.push(liEl)
}const dv = (<div><ul>{songItems}</ul></div>
)

map

  • map方式---推荐
const songs = ['温柔', '倔强', '私奔到月球']const list = songs.map(song => <li>{song}</li>)const dv = (<div><ul>{list}</ul></div>
)

  • map--直接在JSX中渲染--推荐
const songs = ['温柔', '倔强', '私奔到月球']const dv = (<div><ul>{songs.map(song => <li>{song}</li>)}</ul></div>
)

key属性的使用

  • key属性的使用
const dv = (<div><ul>{songs.map(song => (<li key={song}>{song}</li>))}</ul></div>
)

注意:

  • 列表渲染时应该给重复渲染的元素添加key属性,key属性的值要保证唯一
  • key值避免使用index下标,因为下标会发生改变

JSX的本质

实际上,jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖

所有的jsx最终都会被转换成React.createElement的函数调用

可以在babel官网中快速查看转换的过程:Babel · The compiler for next generation JavaScript

createElement需要传递三个参数:

参数一:type

  • 当前ReactElement的类型
  • 如果是标签元素,那么就使用字符串表示 “div”
  • 如果是组件元素,那么就直接使用组件的名称

参数二:config

  • 所有jsx中的属性都在config中以对象的属性和值的形式存储
  • 比如传入className作为元素的class;

参数三:children

  • 存放在标签中的内容,以children数组的方式进行存储
  • 当然,如果是多个元素呢?React内部有对它们进行处理,处理的源码在下方

 

购物车案例

import React, { PureComponent } from 'react'export default class demoClassComponent extends PureComponent {constructor() {super()this.state = {books: [{id: 1,name: '《算法导论》',date: '2023-10-21',price: 65.0,count: 3,},{id: 2,name: '《javaScript编程艺术》',date: '2023-10-21',price: 138.0,count: 2,},{id: 3,name: '《数学之美》',date: '2023-10-21',price: 88.0,count: 6,},{id: 4,name: '《编程珠玑》',date: '2023-10-21',price: 39.0,count: 9,},],}}// 格式化价格formatePrice(price) {return '¥' + Number(price).toFixed(2)}// 总计getTotalPrice() {// 方式一// let totalPrice = 0// for (let i = 0; i < this.state.books.length; i++) {//   const book = books[i]//   totalPrice += book.price * book.count// }// 方式二const totalPrice = this.state.books.reduce((preValue, item) => {return preValue + item.count * item.price}, 0)return totalPrice}// 加// increment(index) {//   const newBooks = [...this.state.books]//   newBooks[index].count += 1//   this.setState({//     books: newBooks,//   })// }// 减// decrement(index) {//   const newBooks = [...this.state.books]//   newBooks[index].count -= 1//   this.setState({//     books: newBooks,//   })// }// 加减逻辑合并changeCount(index, count) {const newBooks = [...this.state.books]newBooks[index].count += countthis.setState({books: newBooks,})}// 删除removeItem(index) {const newBooks = [...this.state.books]newBooks.splice(index, 1)this.setState({books: newBooks,})}renderBooks() {const { books } = this.statereturn (<div><table border="1" collapse="none"><thead><tr><th>序号</th><th>书籍名称</th><th>出版日期</th><th>价格</th><th>购买数量</th><th>操作</th></tr></thead><tbody>{books.map((item, index) => {return (<tr key={item.id}><td>{index + 1}</td><td>{item.name}</td><td>{item.date}</td><td>{this.formatePrice(item.price)}</td><td><buttondisabled={item.count <= 1}onClick={() => this.changeCount(index, -1)}>-</button>{item.count}<button onClick={() => this.changeCount(index, 1)}>+</button></td><td><button onClick={() => this.removeItem(index)}>删除</button></td></tr>)})}</tbody></table><h4>总价格:{this.formatePrice(this.getTotalPrice())}</h4></div>)}renderBookEmpty() {return (<div><h4>购物车为空,请添加书籍</h4></div>)}render() {const { books } = this.statereturn books.length ? this.renderBooks() : this.renderBookEmpty()}
}

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

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

相关文章

网络学习-eNSP配置VRRP

虚拟路由冗余协议(Virtual Router Redundancy Protocol&#xff0c;简称VRRP) VRRP广泛应用在边缘网络中&#xff0c;是一种路由冗余协议&#xff0c;它的设计目标是支持特定情况下IP数据流量失败转移不会引起混乱&#xff0c;允许主机使用单路由器&#xff0c;以及即使在实际…

全球NAND原厂闪存市场格局变化

根据市场研究机构TrendForce的最新跟踪报告&#xff0c;三星&#xff08;Samsung&#xff09;和SK海力士&#xff08;SK hynix-Solidigm&#xff09;在过去的一个季度中扩大了他们在NAND闪存市场的份额&#xff0c;这主要得益于抢占了铠侠&#xff08;Kioxia&#xff09;与西部…

小目标检测顶会新思路!最新成果刷爆遥感SOTA,参数小了18倍

遥感领域的小目标检测一直是个具有挑战性和趣味性的研究方向&#xff0c;同时也是顶会顶刊的常客。但不得不说&#xff0c;今年关于遥感小目标检测的研究热情尤其高涨&#xff0c;已经出现了很多非常优秀的成果。 比如SuperYOLO方法&#xff0c;通过融合多模态数据并执行高分辨…

【重学 MySQL】二十八、SQL99语法新特性之自然连接和 using 连接

【重学 MySQL】二十八、SQL99语法新特性之自然连接和 using 连接 自然连接&#xff08;NATURAL JOIN&#xff09;USING连接总结 SQL99语法在SQL92的基础上引入了一些新特性&#xff0c;其中自然连接&#xff08;NATURAL JOIN&#xff09;和USING连接是较为显著的两个特性。 自…

数据结构(14)——哈希表(1)

欢迎来到博主的专栏&#xff1a;数据结构 博主ID&#xff1a;代码小豪 文章目录 哈希表的思想映射方法&#xff08;哈希函数&#xff09;除留余数法 哈希表insert闭散列负载因子扩容find和erase 哈希表的思想 在以往的线性表中&#xff0c;查找速度取决于线性表是否有序&#…

知识库管理系统在企业数字化转型中的作用

引言 在数字化转型的浪潮中&#xff0c;企业正以前所未有的速度重塑其业务模式、运营流程和组织架构&#xff0c;以适应快速变化的市场环境和客户需求。这一过程中&#xff0c;知识库管理系统作为信息整合与知识共享的核心平台&#xff0c;发挥着举足轻重的作用&#xff0c;不…

【解决】AnimationCurve 运行时丢失数据问题

开发平台&#xff1a;Unity 2022 编程平台&#xff1a;Visual Studio 编程语言&#xff1a;CSharp   一、问题背景 如上图所示的 GracityComponent 组件中&#xff0c;引用 AnimationCurve 作为可调属性。但在实际使用中出现数据丢失问题。大致为以下两种情况&#xff1a; 运…

【重学 MySQL】二十七、七种 join 连接

【重学 MySQL】二十七、七种 join 连接 union 的使用UNION 的基本用法示例UNION ALL 的用法 七种 join 连接代码实现语法格式小结 union 的使用 UNION 在 SQL 中用于合并两个或多个 SELECT 语句的结果集&#xff0c;并默认去除重复的行。如果希望包含重复行&#xff0c;可以使…

RNN发展(RNN/LSTM/GRU/GNMT/transformer/RWKV)

RNN到GRU参考&#xff1a; https://blog.csdn.net/weixin_36378508/article/details/115101779 tRANSFORMERS参考&#xff1a; seq2seq到attention到transformer理解 GNMT 2016年9月 谷歌,基于神经网络的翻译系统&#xff08;GNMT&#xff09;&#xff0c;并宣称GNMT在多个主…

java程序员入行科目一之CRUD轻松入门教程(二)

封装工具类 封装获取连接&释放资源操作 在实际使用JDBC的时候&#xff0c;很多操作都是固定的&#xff0c;没有必要每次都去注册驱动&#xff0c;获取链接对象等等。 同样&#xff0c;释放资源的close操作也可以封装一下 下面是封装好的具体工具类 package com.jimihua.u…

海外云手机是否适合运营TikTok?

随着科技的迅猛发展&#xff0c;海外云手机逐渐成为改变工作模式的重要工具。这种基于云端技术的虚拟手机&#xff0c;不仅提供了更加便捷、安全的使用体验&#xff0c;还在电商引流和海外社媒管理等领域展示了其巨大潜力。那么&#xff0c;海外云手机究竟能否有效用于运营TikT…

mosh java 2.4 inheritance继承

1.面向对象编程的第三个特点 继承 继承的好处 java不能继承多个父级 代码文件结构 1.main.java package org.example; //package org.codewithme;//import org.example.UIControl;//TIP To <b>Run</b> code, press <shortcut actionId"Run"/> or /…

3C电子胶黏剂在手机制造方面有哪些关键的应用

3C电子胶黏剂在手机制造方面有哪些关键的应用 3C电子胶黏剂在手机制造中扮演着至关重要的角色&#xff0c;其应用广泛且细致&#xff0c;覆盖了手机内部组件的多个层面&#xff0c;确保了设备的可靠性和性能。以下是电子胶在手机制造中的关键应用&#xff1a; 手机主板用胶&…

率先搭载存内计算AI芯片,维迈通引领骑行通讯降噪革新

近日&#xff0c;高端骑行头盔耳机领导品牌维迈通&#xff08;VIMOTO&#xff09;三款新品XR、V10S、V10X全平台正式发售&#xff0c;创新搭载了知存科技&#xff08;Witmem&#xff09;高能效存内计算AI芯片&#xff0c;为骑行爱好者带来更极致的AI降噪体验。 作为一家专注摩托…

状压DP

状压DP 对于数据范围n<20的可以考虑状压DP 1.蒙德里安的梦想 题目描述 求把 N M NM NM 的棋盘分割成若干个 12 的的长方形&#xff0c;有多少种方案。 例如当$ N2&#xff0c;M4$ 时&#xff0c;共有 5 种方案。当 N 2 &#xff0c; M 3 N2&#xff0c;M3 N2&…

windows 创建新用户,并分配到指定组

右击电脑 -> 点击管理 在右边右击&#xff0c;选择新用户&#xff0c;输入相关信息创建 创建用户后&#xff0c;选择用户&#xff0c;右击&#xff0c;选择属性&#xff0c;添加 点击高级 点击立即查找&#xff0c;可以搜索出所有可用的组&#xff0c;为其选择即可

Java XML

1、XML文件介绍 配置文件&#xff1a;用来保存设置的一些东西。 拿IDEA来举例&#xff0c;比如设置的背景图片&#xff0c;字体信息&#xff0c;字号信息和主题信息等等。 &#xff08;1&#xff09;以前是用txt保存的&#xff0c;没有任何优点&#xff0c;而且不利于阅读&a…

停车位检测-停车场车位识别

YOLO Parking Spot 概述 停车场获取的图像训练了四个YOLO模型来检测车辆。目标是收集信息&#xff0c;并可能开发一种停车解决方案以改善交通流量并优化空间利用率。通过识别汽车&#xff0c;我们生成了一份报告&#xff0c;其中包含图像细节&#xff0c;如可用停车位的数量、…

官宣:Zilliz 在亚马逊云科技中国区正式开服!

01 Zilliz Cloud 正式上线亚马逊云科技宁夏区服务 9 月 4 日&#xff0c;Zilliz 正式官宣&#xff0c; Zilliz Cloud 正式上线亚马逊云科技在宁夏区的云服务。至此&#xff0c;Zilliz Cloud 已实现全球 5 大云 19 个节点 的全覆盖&#xff0c;成为全球首个提供海内外多云服务的…

《机器学习》—— SVD奇异值分解方法对图像进行压缩

文章目录 一、SVD奇异值分解简单介绍二、代码实现—SVD奇异值分解方法对图像进行压缩 一、SVD奇异值分解简单介绍 SVD&#xff08;奇异值分解&#xff09;是一种在信号处理、统计学、线性代数、机器学习等多个领域广泛应用的矩阵分解方法。它将任何 mn 矩阵 A 分解为三个特定矩…