React(一):初识React、类组件、jsx的基础语法

news/2024/4/24 2:45:33/文章来源:https://blog.csdn.net/weixin_42044763/article/details/129177707

React(一)

  • 一、初识React
    • 1.简单介绍
    • 2.React的三个依赖
    • 3.Hello React案例
  • 二、类组件
    • 1.定义类组件并渲染
    • 2.绑定事件函数(奇怪的this问题)
    • 3.数组形式数据的展示(电影案例)
    • 4.计数器案例
  • 三、jsx语法详解
    • 1.jsx的书写规范
    • 2.jsx的注释
    • 3.jsx嵌入变量
    • 3.jsx嵌入表达式
    • 4.jsx绑定属性

一、初识React

1.简单介绍

React是什么?用于构建用户界面的 JavaScript 库
React的官网文档:https://react.docschina.org/

React的特点:
1、声明式编程:声明式编程是目前整个大前端开发的模式:Vue、React、Flutter、SwiftUI;
在这里插入图片描述

2、组件化开发
3、多平台适配

2.React的三个依赖

1、react:包含react所必须的核心代码
2、react-dom:react渲染在不同平台所需要的核心代码
3、babel:将jsx转换成React代码的工具

依赖的引入有很多方式:
1、直接引入CDN连接
2、下载后添加本地依赖
3、脚手架npm引入

前期的学习中先在html中使用CDN引入(引入React18)

<!-- 引入三个依赖的库 -->
<!-- 1.引入react核心代码库 -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<!-- 2.引入渲染核心代码库 -->
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- 3.引入将jsx转换成react代码的工具库 -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

3.Hello React案例

同样作为MVVM结构的框架,React在渲染DOM的时候也有自己的方式

这里要注意,在React18版本前后,我们的写法是不一样的:

  • React18之前使用ReactDOM.render(html结构或组件,容器)
  • React18之后使用ReactDOM.createRoot(容器).render(html结构或组件)
<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//渲染Hello World//React18之前使用ReactDOM.render// ReactDOM.render(<h2>Hello World</h2>, document.querySelector('#root'));//React18之后const root = ReactDOM.createRoot(document.querySelector('#root'));root.render(<h2>Hello World</h2>);
</script>

接下来是我们的点击按钮切换信息的Hello React案例完整版

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//渲染Hello World//1.定义一个变量来存储信息let message = 'Hello Word!';//React18之前使用ReactDOM.render//ReactDOM.render(<h2>Hello World</h2>, document.querySelector('#root'));//React18之后//2.定义容器const root = ReactDOM.createRoot(document.querySelector('#root'));//3.先调用一次渲染函数,渲染页面rootRender();//下面是预先定义好的函数//函数一:渲染函数function rootRender() {root.render(<div><h2>{message}</h2><button onClick={changeMsg}>点击修改信息</button></div>);}//函数二:按钮的点击事件触发函数function changeMsg() {message = 'Hello React!';console.log(message); //函数调用了,但是没有重新渲染rootRender(); //修改完后重新渲染页面}
</script>

总结,这里和Vue对比有几个不一样的地方:
1、定义容器并渲染的过程,重新渲染要自己调用渲染函数,不像Vue会自动更新页面
2、读取变量使用单括号{ name },不像Vue用双括号{{}}
3、html的结构要作为参数传到render函数中,不像Vue直接编辑html结构
4、点击事件使用onClick={函数名},而Vue是v-on:click="函数名"

二、类组件

在React中有两种定义组件的防止,一种是类组件,另一种是函数组件,这里我们使用ES6的类来声明组件,把刚才的Hello React案例用组件的方式呈现出来。

1.定义类组件并渲染

1、定义类组件,继承React.Component,并继承父类的属性

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//1.定义类组件class App extends React.Component {constructor() {super();}}
</script>

2、添加一个state属性,用来存储数据,名字必须叫state

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//1.定义类组件class App extends React.Component {constructor() {super();this.state = {message: 'hello world',}}}
</script>

3、定义一个render渲染函数,名字必须叫render,当我们拿到容器渲染组件时,就会自动调用这个函数,返回相应的html节点

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//1.定义类组件class App extends React.Component {constructor() {super();this.state = {message: 'hello world',}}render() {return (<div><h2>{this.state.message}</h2><button>点击切换信息</button></div>)}}
</script>

4、拿到容器,渲染组件

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//1.定义类组件class App extends React.Component {constructor() {super();//1.1添加一个state属性存储数据,名字不能改,必须叫statethis.state = {name: 'zzy',message: 'Hello World!',}}//1.3事件函数//1.2渲染函数,名字不能改,必须叫renderrender() {return (<div><h2>{this.state.message}</h2><button onClick={this.changeMsg}>点击修改信息</button></div>)}}//2.拿到容器,渲染组件let root = ReactDOM.createRoot(document.querySelector('#root'));root.render(<App/>);
</script>

2.绑定事件函数(奇怪的this问题)

这里有一个this 的问题,先复习一下严格模式的东西:严格模式
这里要知道:ES6类中的函数都会默认开启严格模式(this指向undefined)

class App {constructor(name) {this.name = name;}changeMsg() {//这里其实默认开启了严格模式console.log(this);}
}//搞清楚this的问题
let app = new App();
let out = app.changeMsg;
out(); //undefined

也就是说,只有类的实例调用类原型上的方法时,this才有指向(指向实例)

这里我们可以看到,直接给按钮绑定了一个事件函数,那么在调用的时候,调用者不是实例,this肯定不指向实例。

调用这个函数就是调用类中的函数,那么this就是undefined,可是这样我们怎么顺着原型链访问setState进而对数据进行更改呢?其实很简单,只需要在constructor中改变事件函数的this指向:

//1.4保存事件函数this指向
this.changeMsg = this.changeMsg.bind(this);
<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">//1.定义类组件class App extends React.Component {constructor() {super();//1.1添加一个state属性存储数据,名字不能改,必须叫statethis.state = {name: 'zzy',message: 'Hello World!',}//1.4保存事件函数this指向this.changeMsg = this.changeMsg.bind(this);}//1.3事件函数changeMsg() {console.log(this);this.setState({message: 'Hello React!',})}//1.2渲染函数,名字不能改,必须叫renderrender() {return (<div><h2>{this.state.message}</h2><button onClick={this.changeMsg}>点击修改信息</button></div>)}}//2.拿到容器,渲染组件let root = ReactDOM.createRoot(document.querySelector('#root'));root.render(<App/>);
</script>

setState这个方法做了两件事:1、更改数据 => 2、重新渲染

3.数组形式数据的展示(电影案例)

方法1:遍历生成li,然后统一放到一个数组里,然后把数组直接展示

<!-- 准备好一个容器 -->
<div id="root"></div><script type="text/babel">class App extends React.Component {constructor() {super();this.state = {movies: ['星际争霸', '魔兽世界', '流浪地球', '奥里给']}}render() {//1.遍历展示数组的方法1let lis = [];for(let i = 0; i < this.state.movies.length; i++) {let movie = this.state.movies[i];let li = <li>{movie}</li>;lis.push(li);}return (<div><h2>电影名字</h2><ul>{lis}</ul></div>      )}}let root = ReactDOM.createRoot(document.querySelector('#root'));root.render(<App/>);
</script>

方法2:使用map遍历数组,返回一个修改后的新数组

render() {//2.方法2,直接映射let lis = this.state.movies.map(el => <li>{el}</li>)return (<div><h2>电影名字</h2><ul>{lis}</ul></div>      )
}

4.计数器案例

点击加一或减一

<div id="root"></div>
<script type="text/babel">const root = ReactDOM.createRoot(document.querySelector('#root'));class App extends React.Component {constructor() {super();this.state = {count: 0,}//改变this的指向this.add = this.add.bind(this);this.subtract = this.subtract.bind(this);}render() {let { count } = this.state;return (<div><h2>{count}</h2><button onClick={this.add}>点击+1</button><button onClick={this.subtract}>点击-1</button></div>)}//事件函数add() {this.setState({// count: this.state.count + 1count: ++this.state.count})}subtract() {this.setState({count: --this.state.count})}}root.render(<App/>);
</script>

三、jsx语法详解

在这里插入图片描述
我们直接把标签赋值给变量,这种写法在原来的js环境会报错,但是在jsx中(开启了babel)就不会报错,这就是一段jsx语法。

  • JSX是一种JavaScript的语法扩展(eXtension)。
  • 它用于描述我们的UI界面,并且其完成可以和JavaScript融合在一起使用;
  • 它不同于Vue中的模块语法,你不需要专门学习模块语法中的一些指令(比如v-for、v-if、v-else、v-bind);

1.jsx的书写规范

React认为渲染逻辑本质上与其他UI逻辑存在内在耦合。
比如UI需要绑定事件,UI需要展示数据,当数据变化时UI又要更新;所以React没有把它们单独分开,而是封装成组件。那么jsx有什么书写规范呢?

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

render() {let { count } = this.state;return (<div><h2>{count}</h2><br/></div>)
}

2、为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写;
3、JSX中的标签可以是单标签,也可以是双标签; 注意:如果是单标签,必须以/>结尾,在html中不用/也行,但在这里会报错;

2.jsx的注释

在大括号中使用/**/包裹注释

render() {let { count } = this.state;return (<div>{/*这是一段注释*/}<h2>{count}</h2></div>)
}

3.jsx嵌入变量

1、String/Number/Array这三种类型都可以正常显示(其中数组会自己拆开)

constructor() {super();this.state = {name: 'zzy', //Stringage: 18,   //Numberhabits:['吃饭','睡觉'] //Array}
}render() {let { name,age,habits } = this.state;return (<div>{/*这是一段注释*/}<h2>{name}</h2><h2>{age}</h2><h2>{habits}</h2></div>)
} 

在这里插入图片描述
2、undefined/null/Boolean这三种类型默认不会显示,因为有时候我们请求数据如果没请求到,那么肯定不能把undefined显示出来。如果非要显示,请连接字符串或toString()

constructor() {super();this.state = {a: undefined, //undefinedb: null, //nullc: true, //Boolean}
}render() {let { a, b, c } = this.state;return (<div><h2>{a}</h2><h2>{b}</h2><h2>{c}</h2></div>)
}

3、Object对象类型作为嵌入变量会报错。

constructor() {super();this.state = {friend: {name: 'ht',age: 18,}}
}render() {let { friend } = this.state;return (<div><h2>{friend}</h2> {/*报错*/}</div>)
}

3.jsx嵌入表达式

1、运算符表达式

constructor() {super();this.state = {firstName: 'zzy',lastName: 'ht',}
}render() {let { firstName, lastName } = this.state;return (<div><h2>{firstName + ' ' + lastName}</h2><h2>{30 + 20}</h2></div>)
}

2、三元表达式

constructor() {super();this.state = {num: 99,}
}render() {let { num } = this.state;return (<div><h2>{num > 10 ? 'big' : 'small'}</h2></div>)
}

3、调用函数获取返回值

constructor() {super();this.state = {num: 99,}
}render() {return (<div><h2>{this.getNum()}</h2></div>)
}getNum() {return this.state.num;
}

4.jsx绑定属性

比如img元素会有src属性、a元素会有href属性、元素可能需要绑定class、原生使用内联样式style等等,都可以动态去绑定。

1、绑定普通属性

constructor() {super();this.state = {imgUrl: "http://p2.music.126.net/L8IDEWMk_6vyT0asSkPgXw==/109951163990535633.jpg",link: 'http://www.baidu.com'}
}render() {let { imgUrl, link } = this.state;return (<div><img src={imgUrl}/><a href={link}>百度</a></div>)
}

2、绑定class样式。在React中,一般用className而不用calss(因为class是类的关键字)

.zzy {color: blue;font-size: 30px;
}

这里动态绑定类名有两种方式,一种是三元表达式+字符串拼接(或模板字符串),一种是定义一个数组,然后push进去再读取数组。

这里要注意,jsx在属性中引用数组时和在页面上展示数据时不一样:
1、属性中引用是用逗号隔开。
2、页面展示则是直接字符串相连。

constructor() {super();this.state = {active: true,msg: '动态绑定类'}
}render() {let { msg, active } = this.state;//动态绑定类名方式一let className = `zzy ${active ? 'active' : ''}`;//动态绑定类名方式二let classArr = ['zzy','ht'];if(active) classArr.push('active');return (<div><h2 className='zzy'>{msg}</h2><h2 className={className}>{msg}</h2>{/*2.绑定class*/}{/*属性动态绑定数组,转为字符串自动逗号隔开*/}{/*展示部分动态绑定数组,转为字符串自动去掉逗号*/}<h2 className={classArr.join(' ')}>{msg}</h2></div>)
}

在这里插入图片描述

3、绑定style样式,这里要使用对象的形式,属性名采用驼峰命名,这里和我们刚才提到的html内容展示是不一样的,内容展示用对象会报错,而属性绑定这里不会报错,即双括号{{}}

constructor() {super();this.state = {msg: '动态绑定style'}
}render() {return (<div>{/*3.绑定style*/}<h2 style={{color:'blue',fontSize:'36px'}}>{this.state.msg}</h2></div>)
}

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

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

相关文章

利用InceptionV3实现图像分类

最近在做一个机审的项目&#xff0c;初步希望实现图像的四分类&#xff0c;即&#xff1a;正常&#xff08;neutral&#xff09;、涉政&#xff08;political&#xff09;、涉黄&#xff08;porn&#xff09;、涉恐&#xff08;terrorism&#xff09;。有朋友给推荐了个github上…

机器学习笔记之近似推断(一)从深度学习角度认识推断

机器学习笔记之近似推断——从深度学习角度认识推断引言推断——基本介绍精确推断难的原因虽然能够表示&#xff0c;但计算代价太大无法直接表示引言 本节是一篇关于推断总结的博客&#xff0c;侧重点在于深度学习模型中的推断任务。 推断——基本介绍 推断(Inference\text{…

Python中实现将内容进行base64编码与解码

一、需求说明需要使用Python实现将内容转为base64编码&#xff0c;解码&#xff0c;方便后续的数据操作。二、base64简介Base64是一种二进制到文本的编码方式【是一种基于 64 个可打印字符来表示二进制数据的表示方法&#xff08;由于 2^664&#xff0c;所以每 6 个比特为一个单…

国产音质好的蓝牙耳机有哪些?国产音质最好的耳机排行

随着时间的推移&#xff0c;真无线蓝牙耳机逐渐占据耳机市场的份额&#xff0c;成为人们日常生活中必备的数码产品之一。蓝牙耳机品牌也多得数不胜数&#xff0c;哪些国产蓝牙耳机音质好&#xff1f;下面&#xff0c;我们从音质出来&#xff0c;来给大家介绍几款国产蓝牙耳机&a…

硬件系统工程师宝典(11)-----去耦电容布局“有讲究”

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们说到在电源完整性分析的目标就是要做到电源的干净、稳定和快速响应&#xff0c;以及针对不同噪声处理的实现方法。今天我们来看看去耦电容…

父传子与子传父步骤

父传子&#xff1a; 问题&#xff1a;父页面中引入子组件 把想要传给子页面的值用在子组件中用 &#xff1a;值“值” (用同一个值好区分)来绑定。 在子页面中用props接收 子组件不能改变父组件传过来的值。&#xff08;传多个页面的时候是&#xff0c;比如父传孙的时候我会…

【2023】华为OD机试真题Java-题目0221-AI处理器组合

AI处理器组合 题目描述 某公司研发了一款高性能AI处理器。每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。编号0-3的处理器处于同一个链路中,编号4-7的处理器处于另外一个链路中,不通链路中的处理器不能通信,如下图所示。现给定服务器可用的处理器编号数…

STM32---备份寄存器BKP和 FLASH学习使用

BKP库函数 学习BKP&#xff0c;首先就是知道BKP每一个函数的作用然后如何使用即可 使用备份域的作用只需要操作上面的两个函数即可&#xff0c;其余的都是它的其他功能 BKP简介 备份寄存器是42个16位的寄存器&#xff0c;可用来存储84个字节的用户应用程序数据。他们处在备份…

如何高效管理自己的时间,可以从这几个方向着手

如果你是上班族&#xff0c;天选打工人&#xff0c;你的绝大多数时间都属于老板&#xff0c;能够自己支配的时间其实并不多&#xff0c;所以你可能察觉不到时间管理的重要性。但如果你是自由职业者或者创业者&#xff0c;想要做出点成绩&#xff0c;那你就需要做好时间管理&…

2. Dart 开发工具环境配置

很多编辑器都可以用来开发dart&#xff0c;所以大家可以选择自己喜欢的编辑器去进行开发。我还是比较喜欢vs code如果你不用vs code来开发dart的话&#xff0c;这篇文章可以直接跳过。如果想要在vs code里有dart的语法提示&#xff0c;我们需要安装相关的插件如图点开插件输入d…

预编译(回顾)

浏览器运行机制变量提升机制私有变量提升步骤全局对象 GO 和全局变量对象 VO的区别带var和不带var的区别系统输出顺序变量提升在条件判断下的处理防止函数的变量提升 浏览器运行机制 为了能够让代码执行&#xff0c;浏览器首先会形成一个执行环境栈 ECStack(Execution Contex…

TCP协议和TCP连接

TCP协议和TCP连接一、TCP协议的简介二、TCP连接的简介1、TCP连接的建立&#xff08;TCP三次握手&#xff09;2、TCP连接的断开&#xff08;TCP四次挥手&#xff09;一、TCP协议的简介 TCP&#xff08;Transmission Control Protocol&#xff09;传输控制协议是一种面向连接的、…

java 接口 详解

目录 一、概述 1.介绍 : 2.定义 : 二、特点 1.接口成员变量的特点 : 2.接口成员方法的特点 : 3.接口构造方法的特点 : 4.接口创建对象的特点 : 5.接口继承关系的特点 : 三、应用 : 1.情景 : 2.多态 : ①多态的传递性 : ②关于接口的多态参数和多态…

股票量化交易SQL特征工程入门

虽然现在各种量化教程和自助平台铺天盖地&#xff0c;但是对于新人来说入门最重要的事情就是挖掘特征。 对于传统的学习路径第一步是学习Python或者某一门编程语言&#xff0c;虽说Python入门容易上手快&#xff0c;但是要在实际应用中对股票数据进行分析&#xff0c;并挖掘有…

2023/2/24 图数据库Neo4j的理解与应用

1 什么是图数据库&#xff08;graph database&#xff09; 十大应用案例&#xff1a;https://go.neo4j.com/rs/710-RRC-335/images/Neo4j-Top-Use-Cases-ZH.pdf “大数据”每年都在增长&#xff0c;但如今的企业领导者不仅需要管理更大规模的数据&#xff0c;还迫切需要从现有…

8000+字,就说一个字Volatile

简介 volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制&#xff1a;同步块&#xff08;或方法&#xff09;和 volatile 变量&#xff0c;相比于synchronized&#xff08;synchronized通常称为重量级锁&#xff09;&#xff0c;volatile更轻量级&…

【大数据】记一次hadoop集群missing block问题排查和数据恢复

问题描述 集群环境总共有2个NN节点&#xff0c;3个JN节点&#xff0c;40个DN节点&#xff0c;基于hadoop-3.3.1的版本。集群采用的双副本&#xff0c;未使用ec纠删码。 问题如下&#xff1a; bin/hdfs fsck -list-corruptfileblocks / The list of corrupt files under path…

汽车零部件行业mes系统具体功能介绍

众所周知&#xff0c;汽车零部件的组装是汽车制造的关键环节&#xff0c;而汽车零部件江湖变革以精益为终极目标。即汽车零部件制造企业转型升级向精益生产和精益管理方向前进&#xff0c;而车间信息化管理是精益化生产的基础。 汽车零部件行业现状 随着全球汽车产业不断升级…

蓝牙标签操作指南

一、APP安装指南 1.APP权限问题 电子标签APP安装之后&#xff0c;会提示一些权限的申请&#xff0c;点击允许。否则某些会影响APP的正常运行。安装后&#xff0c;搜索不到蓝牙标签&#xff0c;可以关闭App&#xff0c;重新打开。 2.手机功能 运行APP时候&#xff0c;需要打开…

Linux基本介绍与常用操作指令

参考链接&#xff1a; Linux面试必备20个常用命令_无 羡ღ的博客-CSDN博客_linux常用命令 1. Linux简介 Linux是一个支持多用户、多任务、多线程和多CPU的操作系统&#xff0c;特点是免费、稳定、高效&#xff0c; 一般运行在大型服务器上。 1.1 常用目录简介 /&#xff1a;根目…