React(二):JSX语法解析+综合案例

事件绑定

this绑定方式

问题:在事件执行后,需获取当前类的对象中相关属性,此时需要this——当打印时,发现this为undefined,这又是为啥?

假设有一个btnClick函数,但它并不是我们主动调用的,而是当button发生改变时,React内部调用→内部调用时,并不知道要如何绑定正确的this

解决办法:

  1. bind给btnClick显示绑定this
  2. 使用 ES6 class fields 语法
  3. 事件监听时传入箭头函数(较为推荐)
<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 type="text/babel">/* this的四种绑定规则 1.默认绑定:独立执行foo()2.隐式绑定:被一个对象执行obj.foo() ->obj3.显示绑定:call/apply/bind  foo.call('aaa') ->String('aaa')4.new绑定:new Foo() -> 创建一个新对象,并赋值给this*///1.创建rootconst root = ReactDOM.createRoot(document.getElementById('root'))//2..定义App根组件class App extends React.Component {constructor() {super()this.state = {count:100}}btn1Click() {this.setState({ count:this.state.count+1})}// 箭头函数无this,只能去上一层找btn2Click = () => {this.setState({ count:this.state.count-1})}btn3Click() {this.setState({ count:this.state.count-1})}render(){const {count} = this.statereturn (<div><h1>{ count }</h1>{/* 1.this绑定方式一:bind绑定 */}<button onClick={this.btn1Click.bind(this)}>按钮1</button>{/* 2.this绑定方式二:箭头函数ES6 class fields */}<button onClick={this.btn2Click}>按钮2</button>{/* 3.this绑定方式三:直接传入一个箭头函数 */}<button onClick={() => this.btn3Click()}>按钮3</button></div>)}}// 3.将App组件渲染到root上root.render(<App />)</script>
</body>
事件参数传递

1.获取默认参数:即event对象

2.获取更多参数:可通过传入一个箭头函数,主动执行的事件函数,并且传入相关的其他参数

<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 type="text/babel">//1.创建rootconst root = ReactDOM.createRoot(document.getElementById('root'))//2..定义App根组件class App extends React.Component {constructor() {super()this.state = {message:"Hello World"}}btnClick (event,name,age) {console.log("点击事件", event,this);console.log("name:", name, "age:",age);}render(){const {message} = this.statereturn (<div>{/* 1.event参数的传递 */}<button onClick={this.btnClick}>按钮1</button><button onClick={(event) => this.btnClick(event)}>按钮2</button>{/* 2.传递额外的参数 */}<button onClick={(event) => this.btnClick(event, "why", 30)}>按钮3</button></div>)}}// 3.将App组件渲染到root上root.render(<App />)</script>
</body>

条件渲染

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

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

常见条件渲染方式:

1.条件判断语句

2.三元运算符

3.与运算符&&

<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 type="text/babel">//1.创建rootconst root = ReactDOM.createRoot(document.getElementById('root'))//2..定义App根组件class App extends React.Component {constructor() {super()this.state = {isReady:true,friend:{name:"lucy",age:22,gender:"女"}}}render(){const {isReady,friend} = this.state// 1.条件判断方式一:使用if进行条件判断let showElement = nullif(isReady) {showElement = <h2>准备开始比赛吧</h2>}else{showElement = <h1>我还没有准备好嘞</h1>}return (<div>{/* 方式一:根据条件给变量赋值不同的内容 */}<div>{ showElement }</div>{/* 方式二:三元运算符 */}<div>{isReady? <button>准备开始</button> : <button>还没有准备好</button> }</div>{/* 方式三:&&运算符 */}{/* 场景:当某一个值,有可能为undefined时,使用&&进行条件判断 */}<div>{ friend && <div>{friend.name + friend.age + friend.gender}</div> }</div></div>)}}// 3.将App组件渲染到root上root.render(<App />)</script>
</body>

实现v-show的效果:

class App extends React.Component {constructor() {super()this.state = {message:"Hello World",isShow:true}}ediClick() {this.setState({isShow:!this.state.isShow})}render(){const {message,isShow} = this.statereturn (<div><button onClick={this.ediClick.bind(this)}>切换1</button><h1 >{ isShow? message : "" }</h1>{/* v-show的效果 */}<button onClick={this.ediClick.bind(this)}>切换2</button><h1 style={{display:isShow ? "block" : "none"}}>{ message }</h1></div>)}
}

列表渲染

class App extends React.Component {constructor() {super()this.state = {students:[{id:1, name:'Jack', age:18},{id:2, name:'Tom', age:20},{id:3, name:'Lucy', age:22},{id:4, name:'Lily', age:24}]}}render(){const {students} = this.state// 展示年龄大于20的const filterStudents = students.filter(item => item.age >= 20)return (<div><h2>学生信息列表</h2><div className="list">{/* 绑定唯一标识key:提高diff算法时的效率 */}{filterStudents.map(item => <div key={item.id} className="item"><p>id:{item.id}</p><p>姓名:{item.name}</p><p>年龄:{item.age}</p></div>)}</div></div>)}
}

原理本质

babel转换

实际上,jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖→所有的jsx最终都会被转换成React.createElement的函数调用

createElement需要传递三个参数:

1.参数一:type

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

2.参数二:config

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

3.参数三:children

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

直接编写jsx代码:

<div><div className="header">header</div><div className="Content"><div>Banner</div><ul><li>数据列表1</li><li>数据列表2</li><li>数据列表3</li></ul></div><div className="footer">footer</div>
</div>

经过babel转译后:

React.createElement(
'div',
null,
React.createElement('div', { className: 'header' }, 'header'),
React.createElement('div',{ className: 'Content' },React.createElement('div', null, 'Banner'),React.createElement('ul',null,React.createElement('li', null, '数据列表1'),React.createElement('li', null, '数据列表2'),React.createElement('li', null, '数据列表3'))
),
React.createElement('div', { className: 'footer' }, 'footer')
);
虚拟DOM生成

通过React.createElement最终创建出一个ReactElement对象→它组成了一个JS对象树→即虚拟DOM

阶段案例-购物车

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

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},
]

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

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

相关文章

One of the configured repositories failed (未知), and yum doesn‘t have enough cached data to continue

centos操作系统运行yum命令是出现如下报错&#xff1a; 解决办法&#xff1a; 由于CentOS的源地址内容已移除&#xff0c;CentOS 操作系统结束了生命周期&#xff0c;源地址内容已移除。 只需要将它的base源换成其他可用源&#xff0c;我这里将它换成了阿里的base源 备份原来…

【蓝图使用】绘制mesh顶点的法线

文章目录 绘制法线Normal准备工作UE5资源制作蓝图制作 参考 绘制法线Normal 参考[1]打算用蓝图走一遍渲染管线&#xff0c;还是可以的 准备工作 Blender制作一个三个顶点的模型 要不要材质无所谓&#xff0c;就一个三个顶点的mesh即可&#xff0c;参考[2] 找到一个法线贴…

202503执行jmeter压测数据库(ScyllaDB,redis,lindorm,Mysql)

一、Mysql 1 、 准备MySQL 连接内容 2 、 下载连接jar包 准备 mysql-connector-java-5.1.49.jar 放到 D:\apache-jmeter-5.6.3\lib\ext 目录下面; 3 、 启动jmeter ,配置脚本 添加线程组---》JDBC Connection Configuration---》JDBC Request---》查看结果树。 1)测…

f-string高级字符串格式化与string Template()

f-string 高级字符串格式化 f-string无法替换带有${name}的字符串&#xff0c;会保留\$ def test_fstring():"""f-string&#xff0c;高级字符串格式化的方式"""s "my name is {name}".format(name李白)print(s)# 无法替换$s &quo…

【Java 优选算法】分治-归并排序

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 数组分块如二叉树的前序遍历, 而归并排序就如二叉树的后序遍历 912. 排序数组 解法 使用归并算法 根据中间点划分区间, mid (right left ) / 2将左右区间排序合并两个有…

docker入门篇

使用docker可以很快部署相同的环境,这也是最快的环境构建,接下来就主要对docker中的基础内容进行讲解.Docker 是一个用于开发、交付和运行应用程序的开源平台&#xff0c;它可以让开发者将应用程序及其依赖打包到一个容器中&#xff0c;然后在任何环境中运行这个容器&#xff0…

Learning vtkjs之ContourLoopExtraction

过滤器 等高线轮廓提取 介绍 这个过滤器可以获取一个cut的相交的循环的线&#xff0c;目前这个案例cut是一个平面&#xff0c;应该是可以支持更多隐式公式 效果 可以设置这个平面的原点Origin 法线方向Normal&#xff0c;然后就可以求交了 核心代码 需要实现这个代码主要…

如何高效解决 Java 内存泄漏问题方法论

目录 一、系统化的诊断与优化方法论 二、获取内存快照&#xff1a;内存泄漏的第一步 &#xff08;一&#xff09;自动生成 Heap Dump &#xff08;二&#xff09;手动生成 Heap Dump 三、导入分析工具&#xff1a;MAT 和 JProfiler &#xff08;一&#xff09;MAT (Memor…

新手村:数据预处理-异常值检测方法

机器学习中异常值检测方法 一、前置条件 知识领域要求编程基础Python基础&#xff08;变量、循环、函数&#xff09;、Jupyter Notebook或PyCharm使用。统计学基础理解均值、中位数、标准差、四分位数、正态分布、Z-score等概念。机器学习基础熟悉监督/无监督学习、分类、聚类…

大模型-提示词调优

什么是提示词 提示词&#xff08;Prompt&#xff09;在大模型应用中扮演着关键角色&#xff0c;它是用户输入给模型的一段文本指令 。简单来说&#xff0c;就是我们向大模型提出问题、请求或描述任务时所使用的文字内容。例如&#xff0c;当我们想让模型写一篇关于春天的散文&a…

VS2022输入 scanf 报错解决方法

1.第一种解决办法&#xff08;不推荐&#xff09; •将 scanf 替换为 scanf_s •scanf_s 是VS提供的一个函数&#xff0c;scanf_s函数的使用和scanf是有区别的 •scanf_s 是VS提供的一个函数&#xff0c;其他的编译器可能不认识这个函数&#xff0c;那么我们所写的代码就存在跨…

鸿蒙开发-一多开发之媒体查询功能

在HarmonyOS中&#xff0c;使用ArkTS语法实现响应式布局的媒体查询是一个强大的功能&#xff0c;它允许开发者根据不同的设备特征&#xff08;如屏幕尺寸、屏幕方向等&#xff09;动态地调整UI布局和样式。以下是一个使用媒体查询实现响应式布局的实例&#xff1a; 1. 导入必要…

火语言RPA--列表项内容获取

【组件功能】&#xff1a;获取列表中某项数据内容 配置预览 配置说明 获取 获取数据方式 首项&#xff1a;列表第一条数据 末项&#xff1a;列表最后一条数据 随机项&#xff1a;随机获取列表中一条数据 指定索引项&#xff1a;根据索引获取列表对象中数据。 索引项目位置 …

基于Python+Flask+MySQL+HTML的爬取豆瓣电影top-250数据并进行可视化的数据可视化平台

FlaskMySQLHTML 项目采用前后端分离技术&#xff0c;包含完整的前端&#xff0c;以flask作为后端 Pyecharts、jieba进行前端图表展示 通过MySQL收集格列数据 通过Pyecharts制作数据图表 这是博主b站发布的详细讲解&#xff0c;感兴趣的可以去观看&#xff1a;【Python爬虫可…

解锁MySQL 8.0.14源码调试:Mac 11.6+CLion 2024.3.4实战指南

文章目录 解锁MySQL 8.0.41源码调试&#xff1a;Mac 11.6CLion 2024.3.4实战指南前期准备环境搭建详细步骤安装 CLion安装 CMake 3.30.5准备 MySQL 8.0.14 源码配置 CMake 选项构建 MySQL 项目 调试环境配置与验证配置 LLDB 调试器启动调试验证调试环境 总结与拓展 解锁MySQL 8…

81.HarmonyOS NEXT 状态管理与响应式编程:@Observed深度解析

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 状态管理与响应式编程&#xff1a;Observed深度解析 文章目录 HarmonyOS NEXT 状态管理与响应式编程&#xff1a;Observed深度解析…

【快速入门】MyBatis

一.基础操作 1.准备工作 1&#xff09;引入依赖 一个是mysql驱动包&#xff0c;一个是mybatis的依赖包&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><vers…

RabbitMQ可靠性进制

文章目录 1.生产者可靠性生产者重连生产者确认小结 2. MQ的可靠性数据持久化LazyQueue小结 3. 消费者的可靠性消费者确认机制消费者失败处理方案业务幂等性唯一消息ID业务判断 兜底方案业务判断 兜底方案 1.生产者可靠性 生产者重连 在某些场景下由于网络波动&#xff0c;可能…

【专项测试】限流测试

简介 限流的目的是防止恶意请求、恶意攻击&#xff0c;或者防止流量超出系统峰值时保护系统免受灭顶之灾。 限流的具体做法是是通过对并发访问/请求进行限速或者对一个时间窗口的请求进行限速在保护系统&#xff0c;一旦达到限制速率则可以拒绝服务&#xff08;定向到错误页&a…

Qt-D指针与Q指针的设计哲学

文章目录 前言PIMLP与二进制兼容性D指针Q指针优化d指针继承Q_D和Q_Q 前言 在探索Qt源码的过程中会看到类的成员有一个d指针&#xff0c;d指针类型是一个private的类&#xff0c;这种设计模式称为PIMPL&#xff08;pointer to implementation&#xff09;&#xff0c;本文根据Q…