当前位置: 首页 > news >正文

【React基础】– JSX语法

文章目录

    • 认识JSX
      • 为什么React选择了JSX
      • JSX的使用
    • React事件绑定
      • this的绑定问题
      • 事件参数传递
    • React条件渲染
    • React列表渲染
      • 列表中的key
    • JSX的本质
      • createElement源码
      • Babel官网查看
      • 直接编写jsx代码
    • 虚拟DOM的创建过程
      • jsx – 虚拟DOM – 真实DOM
      • 声明式编程
    • 阶段案例练习


认识JSX


这段element变量的声明右侧赋值的标签语法是什么呢?

​  它不是一段字符串(因为没有使用引号包裹);

​  它看起来是一段HTML元素,但是我们能在js中直接给一个变量赋值html吗?

​  其实是不可以的,如果我们将 type=“text/babel” 去除掉,那么就会出现语法错误;

​  它到底是什么呢?其实它是一段jsx的语法

JSX是什么?

​  JSX是一种JavaScript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起就是一段XML语法

​  它用于描述我们的UI界面,并且其完成可以和JavaScript融合在一起使用

​  它不同于Vue中的模块语法,你不需要专门学习模块语法中的一些指令(比如v-for、v-if、v-else、v-bind);


为什么React选择了JSX


React认为渲染逻辑本质上与其他UI逻辑存在内在耦合

​  比如UI需要绑定事件(button、a原生等等);

​  比如UI中需要展示数据状态

​  比如在某些状态发生改变时,又需要改变UI

◼ 他们之间是密不可分,所以React没有将标记分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件(Component);

​  当然,后面我们还是会继续学习更多组件相关的东西;

◼ 在这里,我们只需要知道,JSX其实是嵌入到JavaScript中的一种结构语法;

JSX的书写规范:

​  JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个div元素(或者使用后面我们学习的Fragment);

​  为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写;

​  JSX中的标签可以是单标签,也可以是双标签

​ ✓ 注意:如果是单标签,必须以/>结尾;


JSX的使用


jsx中的注释

JSX嵌入变量作为子元素

 情况一:当变量是Number、String、Array类型时,可以直接显示

 情况二:当变量是null、undefined、Boolean类型时,内容为空;

​ ✓ 如果希望可以显示null、undefined、Boolean,那么需要转成字符串;

​ ✓ 转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;

 情况三:Object对象类型不能作为子元素(not valid as a React child)

JSX嵌入表达式

 运算表达式

 三元运算符

 执行一个函数


React事件绑定


如果原生DOM原生有一个监听事件,我们可以如何操作呢?

​  方式一:获取DOM原生,添加监听事件;

​  方式二:在HTML原生中,直接绑定onclick;

◼ **在React中是如何操作呢?**我们来实现一下React中的事件监听,这里主要有两点不同

​  React 事件的命名采用小驼峰式(camelCase),而不是纯小写

​  我们需要通过{}传入一个事件处理函数,这个函数会在事件发生时被执行;


this的绑定问题


在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this

​  如果我们这里直接打印this,也会发现它是一个undefined

为什么是undefined呢?

​  原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;

​  而它内部调用时,并不知道要如何绑定正确的this;

如何解决this的问题呢?

 方案一:bind给btnClick显示绑定this

 方案二:使用 ES6 class fields 语法

 方案三:事件监听时传入箭头函数(个人推荐)


事件参数传递


在执行事件函数时,有可能我们需要获取一些参数信息:比如event对象、其他参数

情况一:获取event对象

​  很多时候我们需要拿到event对象来做一些事情(比如阻止默认行为)

​  那么默认情况下,event对象有被直接传入,函数就可以获取到event对象;

情况二:获取更多参数

​  有更多参数时,我们最好的方式就是传入一个箭头函数,主动执行的事件函数,并且传入相关的其他参数

在这里插入图片描述


React条件渲染


某些情况下,界面的内容会根据不同的情况显示不同的内容,或者决定是否渲染某部分内容:

​  在Vue中,我们会通过指令来控制:比如v-if、v-show;

​  在React中,所有的条件判断都和普通的JavaScript代码一致

常见的条件渲染的方式有哪些呢?

方式一:条件判断语句

​  适合逻辑较多的情况

方式二:三元运算符

​  适合逻辑比较简单

方式三:与运算符&&

​  适合如果条件成立,渲染某一个组件;如果条件不成立,什么内容也不渲染;

v-show的效果

​  主要是控制display属性是否为none


React列表渲染


真实开发中我们会从服务器请求到大量的数据,数据会以列表的形式存储:

​  比如歌曲、歌手、排行榜列表的数据;

​  比如商品、购物车、评论列表的数据;

​  比如好友消息、动态、联系人列表的数据;

在React中并没有像Vue模块语法中的v-for指令,而且需要我们通过JavaScript代码的方式组织数据,转成JSX:

​  React中的JSX正是因为和JavaScript无缝的衔接,让它可以更加的灵活

如何展示列表呢?

​  在React中,展示列表最多的方式就是使用数组的map高阶函数

很多时候我们在展示一个数组中的数据之前,需要先对它进行一些处理:

​  比如过滤掉一些内容:filter函数

​  比如截取数组中的一部分内容:slice函数

 <script type="text/babel">// 1.定义App根组件class App extends React.Component {constructor() {super()this.state = {students: [{ id: 111, name: "why", score: 199 },{ id: 112, name: "kobe", score: 98 },{ id: 113, name: "james", score: 199 },{ id: 114, name: "curry", score: 188 },]}}render() {const { students } = this.state// 分数大于100的学生进行展示const filterStudents = students.filter(item => {return item.score > 100})// 分数大于100, 只展示两个人的信息// slice(start, end): [start, end)const sliceStudents = filterStudents.slice(0, 2)return (<div><h2>学生列表数据</h2><div className="list">{students.filter(item => item.score > 100).slice(0, 2).map(item => {return (<div className="item"><h2>学号: {item.id}</h2><h3>姓名: {item.name}</h3><h1>分数: {item.score}</h1></div>)})}</div></div>)}}// 2.创建root并且渲染App组件const root = ReactDOM.createRoot(document.querySelector("#root"))root.render(<App/>)</script>

列表中的key


我们会发现在前面的代码中只要展示列表都会报一个警告:

这个警告是告诉我们需要在列表展示的jsx中添加一个key。

​  key主要的作用是为了提高diff算法时的效率;

​  这个我们在后续内容中再进行讲解;


JSX的本质


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

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

createElement需要传递三个参数:

◼ 参数一:type

​  当前ReactElement的类型;

​  如果是标签元素,那么就使用字符串表示 “div”;

​  如果是组件元素,那么就直接使用组件的名称;

◼ 参数二:config

​  所有jsx中的属性都在config中以对象的属性和值的形式存储;

​  比如传入className作为元素的class;

◼ 参数三:children

​  存放在标签中的内容,以children数组的方式进行存储;

​  当然,如果是多个元素呢?React内部有对它们进行处理,处理的源码在下方


createElement源码


在这里插入图片描述


Babel官网查看


我们知道默认jsx是通过babel帮我们进行语法转换的,所以我们之前写的jsx代码都需要依赖babel。

可以在babel的官网中快速查看转换的过程:https://babeljs.io/repl/#?presets=react


直接编写jsx代码


我们自己来编写React.createElement代码:

​  我们就没有通过jsx来书写了,界面依然是可以正常的渲染。

​  另外,在这样的情况下,你还需要babel相关的内容吗?不需要了

​ ✓ 所以,type="text/babel"可以被我们删除掉了;

​ ✓ 所以,<script src="../react/babel.min.js"></script>可以被我们删除掉了;

在这里插入图片描述


虚拟DOM的创建过程


我们通过 React.createElement 最终创建出来一个 ReactElement对象:

这个ReactElement对象是什么作用呢?React为什么要创建它呢?

​  原因是React利用ReactElement对象组成了一个JavaScript的对象树

​  JavaScript的对象树就是虚拟DOM(Virtual DOM)

如何查看ReactElement的树结构呢?

​  我们可以将之前的jsx返回结果进行打印

​  注意下面代码中我打jsx的打印;

而ReactElement最终形成的树结构就是Virtual DOM;


jsx – 虚拟DOM – 真实DOM


在这里插入图片描述


声明式编程


虚拟DOM帮助我们从命令式编程转到了声明式编程的模式

◼ **React官方的说法:**Virtual DOM 是一种编程理念。

​  在这个理念中,UI以一种理想化或者说虚拟化的方式保存在内存中,并且它是一个相对简单的JavaScript对象

​  我们可以通过ReactDOM.render让 虚拟DOM 和 真实DOM同步起来,这个过程中叫做协调(Reconciliation);

◼ 这种编程的方式赋予了React声明式的API:

​  你只需要告诉React希望让UI是什么状态;

​  React来确保DOM和这些状态是匹配的;

​  你不需要直接进行DOM操作,就可以从手动更改DOM、属性操作、事件处理中解放出来;

关于虚拟DOM的一些其他内容,在后续的学习中还会再次讲到;


阶段案例练习


◼ 1.在界面上以表格的形式,显示一些书籍的数据;

◼ 2.在底部显示书籍的总价格;

◼ 3.点击+或者-可以增加或减少书籍数量(如果为1,那么不能继续-);

◼ 4.点击移除按钮,可以将书籍移除(当所有的书籍移除完毕时,显示:购物车为空~);

在这里插入图片描述

format.js

function formatPrice(price) {return "¥" + Number(price).toFixed(2)
}

data.js

const books = [{id: 1,name: '《算法导论》',date: '2006-9',price: 85.00,count: 1},{id: 2,name: '《UNIX编程艺术》',date: '2006-2',price: 59.00,count: 1},{id: 3,name: '《编程珠玑》',date: '2008-10',price: 39.00,count: 1},{id: 4,name: '《代码大全》',date: '2006-3',price: 128.00,count: 1},
]

案例:

<!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>购物车案例</title><style>table {border-collapse: collapse;text-align: center;}thead {background-color: #f2f2f2;}td, th {padding: 10px 16px;border: 1px solid #aaa;}</style>
</head>
<body><div id="root"></div><script src="../lib/react.js"></script><script src="../lib/react-dom.js"></script><script src="../lib/babel.js"></script><script src="./data.js"></script><script src="./format.js"></script><script type="text/babel">// 1.定义App根组件class App extends React.Component {constructor() {super()this.state = {books: books}}getTotalPrice() {const totalPrice = this.state.books.reduce((preValue, item) => {return preValue + item.count * item.price}, 0)return totalPrice}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 })}renderBookList() {const { books } = this.statereturn <div><table><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>{formatPrice(item.price)}</td><td><button disabled={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><h2>总价格: {formatPrice(this.getTotalPrice())}</h2></div>}renderBookEmpty() {return <div><h2>购物车为空, 请添加书籍~</h2></div>}render() {const { books } = this.statereturn books.length ? this.renderBookList(): this.renderBookEmpty()}}// 2.创建root并且渲染App组件const root = ReactDOM.createRoot(document.querySelector("#root"))root.render(<App/>)</script></body>
</html>

相关文章:

【React基础】– JSX语法

文章目录 认识JSX为什么React选择了JSXJSX的使用 React事件绑定this的绑定问题事件参数传递 React条件渲染React列表渲染列表中的key JSX的本质createElement源码Babel官网查看直接编写jsx代码 虚拟DOM的创建过程jsx – 虚拟DOM – 真实DOM声明式编程 阶段案例练习 认识JSX ◼ …...

SpringBoot 项目中后端实现跨域的5种方式!!!

文章目录 SpringBoot 项目中后端实现跨域的5种方式&#xff01;&#xff01;&#xff01;一、为什么会出现跨域问题二、什么是跨域三、非同源限制四、Java后端 实现 CORS 跨域请求的方式1、返回新的 CorsFilter(全局跨域)2、重写 WebMvcConfigurer(全局跨域)3、使用注解 (局部跨…...

Vue3前端开发,provide和enject的基础练习,跨层级传递数据

Vue3前端开发,provide和enject的基础练习,跨层级传递数据&#xff01; 声明:provide虽然可以跨层级传递&#xff0c;但是依旧是需要由上向下的方向传递。根传子的方向。 <script setup> import {onMounted, ref} from vue import Base from ./components/Base.vue impor…...

Python 循环结构值while循环

while循环是一种常用的循环结构&#xff0c;它会在满足特定条件的情况下重复执行一段代码块。 基本语法&#xff1a; while condition:# 循环体代码while循环的执行过程如下&#xff1a; 首先&#xff0c;判断循环条件condition&#xff08;布尔表达式&#xff09;是否为真。…...

MSSQL-识别扩展extended event(扩展事件)中的时间单位

经常使用sqlserver extended event(扩展事件)&#xff0c;但是总是忘记扩展事件使用的时间单位&#xff0c;不确定它们是 秒、毫秒、还是微秒&#xff1f; 以下下代码能够从 相关DMV中提取description字段内容来识别时间单位&#xff1a; SELECT [p].[name] [package_name],[o…...

vue3中l和vue2中v-model不同点

vue2比较让人诟病的一点就是提供了两种双向绑定&#xff1a;v-model和.sync&#xff0c; 在vue3中&#xff0c;去掉了.sync修饰符&#xff0c;只需要使用v-model进行双向绑定即可。 为了让v-model更好的针对多个属性进行双向绑定&#xff08;vue2中自定义组件中v-model只能使用…...

使用 Swift 代码优化项目编译速度

引言 软件的性能是评价一个软件质量的重要指标&#xff0c;尤其在今天这个时代&#xff0c;性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件&#xff0c;如网银系统、在线购物商城等&#xff0c;更是必须保证其高效稳定的性能。在这种背景下&#xff0c;优化…...

基于springboot+vue的社区团购系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…...

three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera</title><script src"ThreeJS/three.js"></script><script src&qu…...

Golang 搭建 WebSocket 应用(七) - 性能、可用性

在前面的文章中&#xff0c;提到过非功能性需求决定了架构。 今天我们再来考虑一下另外两个非功能性需求&#xff1a;性能和可用性。 前言 关于性能&#xff0c;其实并不是只有我们这个消息推送系统独有的问题。 对于所有的开发者而言&#xff0c;都多多少少会处理过性能相关…...

Qt 状态机框架:The State Machine Framework (一)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 一、什么是状态机框架 状态机框架提供了用于创建和执行状态图/表[1]的类。这些概念和表示法基于Harel的Statecharts:一种复杂系统的可视化形式,也是UML状态图的基…...

高通平台学习一

什么是QMI? Qualcom Message Interface 高通信息接口 高通平台目前都是非对称多核心&#xff0c;最主要的是AP和Modem。两个处理器怎么进行通信呢&#xff0c;我们把AP和Modem当作两个主机&#xff0c;问题就变得了很简单&#xff0c;TCP/IP协议不是一种非常成功的进程间跨主…...

Python爬虫时被封IP,该怎么解决?四大动态IP平台测评

在使用 Python 进行爬虫时&#xff0c;很有可能因为一些异常行为被封 IP&#xff0c;这主要是因为一些爬虫时产生的异常行为导致的。 在曾经的一次数据爬取的时候&#xff0c;我尝试去爬取Google地图上面的商家联系方式和地址信息做营销&#xff0c;可是很不幸&#xff0c;还只…...

积分梳状滤波器CIC原理与实现

CIC&#xff08;Cascade Intergrator Comb&#xff09;&#xff1a;级联积分梳状滤波器&#xff0c;是由积分器和梳状滤波器级联而得。滤波器系数为1&#xff0c;无需对系数进行存储&#xff0c;只有加法器、积分器和寄存器&#xff0c;资源消耗少&#xff0c;运算速率高&#…...

【项目管理】CMMI-原因分析与解决过程(CAR)

概述&#xff1a; “原因分析与解决”通过预防缺陷或者问题的引入以及识别并适当纳入优秀过程性能的原因&#xff0c;改进质量与生产率。 目录 1、文档结构 2、原因分析与解决过程域包括如下活动 3、选择需要加以分析的结果(启动条件) 4、过程活动与实践对照表 5、实例 1、…...

【设计模式】文件目录管理是组合模式吗?

组合模式是什么&#xff1f; 组合模式是一种将对象组合成树形结构以表示"部分-整体"的层次结构的设计模式。它使得用户对单个对象和组合对象的使用具有一致性。 组合模式在什么情况下使用&#xff1f; 当你发现你需要在代码中实现树形数据结构&#xff0c;让整体-部…...

利用appium自动控制移动设备并提取数据

安装appium-python-client模块并启动已安装好的环境 安装appium-python-client模块 在window的虚拟环境下执行pip install appium-python-client 启动夜神模拟器&#xff0c;进入夜神模拟器所在的安装路径的bin目录下&#xff0c;进入cmd终端&#xff0c;使用adb命令建立adb…...

day22_236二叉树最近公共祖先_235二叉搜索树(最近公共祖先_701插入一个节点_450删除一个节点)

文章目录 [236 二叉树的最近公共祖先](https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE)[235 二叉搜索树的最近公共祖先](https://program…...

OpenSource - 工具管理器easy-manager-tool

文章目录 功能说明运行配置环境配置启动docker部署 项目安全UI展示 Easy-Manager-Tool 打造软件行业首款集成工具&#xff0c;不管你是程序员&#xff0c;测试&#xff0c;运维等都可以使用该软件来提升自己的工作效率。 Easy-Manager-Tool 的诞生是为了解决软件行业众多参与者…...

Laravel7 + easyWeChat 实现微信公众号支付功能

注册服务号&#xff0c;需进行微信认证&#xff0c;此时需缴费 300 元/年&#xff0c;必须是认证成功的服务号才能开通微信支付。 注册微信支付商户号 1、登录 https://pay.weixin.qq.com/index.php/core/home/login?return_urlhttps%3A%2F%2Fpay.weixin.qq.com%2Findex.php%…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...