【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>

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

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

相关文章

10个常考的前端手写题,你全都会吗?

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 今天来分享一下10个常见的JavaScript手写功能。 目录 1.实现new 2.call、apply、…

Python爬虫---scrapy框架---当当网管道封装

项目结构&#xff1a; dang.py文件&#xff1a;自己创建&#xff0c;实现爬虫核心功能的文件 import scrapy from scrapy_dangdang_20240113.items import ScrapyDangdang20240113Itemclass DangSpider(scrapy.Spider):name "dang" # 名字# 如果是多页下载的话, …

transbigdata笔记:轨迹切片

1 方法介绍 在transbigdata笔记&#xff1a;轨迹停止点和行程提取-CSDN博客中&#xff0c;已经可以把轨迹点拆分成停止点和行程点&#xff0c;但是行程点只有起止位置&#xff0c;不包含行程轨迹信息为了进一步分析车辆的行驶轨迹&#xff0c;需要从每次行程的时间段中提取轨迹…

matlab Robotics Toolbox

工具箱下载地址&#xff1a;ROBOTICS TOOLBOX 安装教程 笛卡尔运动规划 在MATLAB中&#xff0c;ctraj和jtraj是两个不同的函数&#xff0c;主要用于控制系统和机器人学中的轨迹规划。它们之间的主要区别在于它们处理的问题类型和使用方式。 ctraj&#xff08;连续时间轨迹规划…

CTF CRYPTO 密码学-2

题目名称&#xff1a;crypto1 题目描述&#xff1a; 字符 ZZZZ X XXZ ZZ ZXZ Z ZXZ ZX ZZX XXX XZXX XXZ ZX ZXZZ ZZXZ XX ZX ZZ 分析 此字段是由Z和X组成的字符&#xff0c;联想到莫斯密码是由.和-组成的所以接下来可以尝试莫斯密码解题 解题过程&#xff1a; Step1&#xf…

2019年认证杯SPSSPRO杯数学建模C题(第二阶段)保险业的数字化变革全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 基于统计建模的车险业数字变革研究 C题 保险业的数字化变革 原题再现&#xff1a; 车险&#xff0c;即机动车辆保险。保险自身是一种分散风险、消化损失的经济补偿制度&#xff0c;车险即为分散机动车辆在行驶过程中可能发作的未知风险和损失…

【Vue】Vue 路由的配置及使用

目录捏 前言一、路由是什么&#xff1f;1.前端路由2.后端路由 二、路由配置1.安装路由2.配置路由 三、路由使用1.route 与 router2. 声明式导航3. 指定组件的呈现位置 四、嵌套路由&#xff08;多级路由&#xff09;五、路由重定向1.什么是路由重定向&#xff1f;2.设置 redire…

C++类与对象【友元】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;C从基础到进阶 &#x1f384;1 友元&#x1f951;1.1 全局函数做友元&#x1f951;1.2 类做友元&#x1f951;1.3 成员函数做友元 &#x1f56e;2 总结 &#x1f384;1 友元 生活中你的家…

深入了解性能优化(web应用)

影响一个系统性能的方方面面 一个 web应用不是一个孤立的个体,它是一个系统的部分,系统中的每一部分都会影响整个系统的性能 一.常用的性能评价/测试指标 1.响应时间 提交请求和返回该请求的响应之间使用的时间,一般比较关注平均响应时间。 常用操作的响应时间列表: 操作 响应…

探索 2024 年新副业:无人饮品机的新风向

随着科技的迅猛发展&#xff0c;无人饮品机作为一种全新的商业模式&#xff0c;正逐渐成为 2024 年副业的新风向。如果你还没有了解过这种全新的副业&#xff0c;那么现在是时候深入了解一下了。 D咖无人饮品机的优势在于其 24 小时不间断的营业模式&#xff0c;它可以在你睡觉…

web前端项目-中国象棋【附源码】

中国象棋 【中国象棋】是一款历史悠久、深受人们喜爱的策略类游戏。在Web前端技术中&#xff0c;我们可以使用HTML、CSS和JavaScript等语言来制作一款中国象棋游戏。玩家使用棋子&#xff08;帅/相/士/炮/马/车/炮/卒&#xff09;在棋盘上相互对弈&#xff0c;将对手的“帅”棋…

工作流管理框架airflow-安装部署教程

1 概述 Airflow是一个以编程方式编写&#xff0c;用于管理和调度工作流的平台。可以帮助你定义复杂的工作流程,然后在集群上执行和监控这些工作流。 Airflow计划程序在遵循指定的依赖项&#xff0c;同时在一组工作线程上执行任务。丰富的命令实用程序使在DAG上执行复杂的调度…

国产开源模型标杆,能力比肩ChatGPT!书生·浦语2.0发布,支持免费商用

1月17日&#xff0c;新一代大语言模型书⽣浦语2.0&#xff08;InternLM2&#xff09;正式发布并开源。 2种参数规格、3种模型版本&#xff0c;共计6个模型&#xff0c;全部免费可商用。 它支持200K超长上下文&#xff0c;可轻松读200页财报。200K文本全文范围关键信息召回准确…

Springboot日志框架logback与log4j2

目录 Springboot日志使用 Logback日志 日志格式 自定义日志格式 日志文件输出 Springboot启用log4j2日志框架 Springboot日志使用 Springboot底层是使用slf4jlogback的方式进行日志记录 Logback日志 trace&#xff1a;级别最低 debug&#xff1a;调试级别的&#xff0c…

Windows平台反调试技术学习

前言 前俩天的学习记录Windows上面的反调试学习&#xff0c;主要是参考《恶意代码实战分析》和《加密与解密》里面的&#xff0c;给每个小技术都写了程序示例&#xff0c;自己编译反调试了一遍。对于加解密一书是还有很多不理解的地方的&#xff0c;目前只能记录到这了&#x…

建筑类中级工程师职称证明业绩材料有哪些?

三、建筑类中级工程师职称造价类工程业绩材料 1.合同&#xff1a;证明项目合作关系的凭证。 2.预&#xff08;结&#xff09;算报告等(重点是体现封面有你的名字和执业印章等) 3.单位证明或任命书(本人在项目中的职务聘书) 4.工程获奖证明&#xff1a;项目获得市优的证书、省优…

Ubuntu 22.04.1 LTS VirtualBox7.0 解决虚拟机窗口失去焦点一段时间后,虚拟机显示不刷新问题

故障描述&#xff1a; virtualbox安装在ubuntu系统上&#xff0c;虚拟机内安装了windows操作系统。使用中发现&#xff0c;当linux系统窗口被激活&#xff0c;如firefox浏览器&#xff0c;虚拟机的显示一段时间后会暂停刷新&#xff0c;鼠标划入虚拟机窗口后&#xff0c;才会立…

分布式概念

文章目录 一、CAP定理和BASE定理1.1 CAP定理1.2 CAP取舍1.3 BASE定理 二、分布式事务2.1 柔性事务2.2 两阶段提交协议2.3 三阶段提交协议 三、分布式ID3.1 数据库自增ID3.2 数据库多主模式3.3 号段模式3.4 雪花算法3.5 Leaf3.6 使用Redis生成ID 四、限流算法4.1 固定窗口计数器…

TypeScript实现一个贪吃蛇小游戏

游戏效果 文件目录 准备1&#xff1a;新建index.html&#xff0c;编写游戏静态页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-…

小程序开发实战案例五 | 小程序如何嵌入H5页面

在接入小程序过程中会遇到需要将 H5 页面集成到小程序中情况&#xff0c;今天我们就来聊一聊怎么把 H5 页面塞到小程序中。 本篇文章将会从下面这几个方面来介绍&#xff1a; 小程序承载页面的前期准备小程序如何承载 H5小程序和 H5 页面如何通讯小程序和 H5 页面的相互跳转 小…