React简介
大约 19 分钟
React简介
以下为学习过程中的极简提炼笔记,以供重温巩固学习
学习准备
准备工作
html+css+JavaScript vue
其中需要掌握JavaScript中的
- 判断this的指向
- class(类)、实例、继承
- ES6语法规范(箭头函数、模板字符串、解构赋值)
- npm等包管理器(学习react脚手架时需要)
- 原型&原型链
- 数组的常用方法(统计、遍历、过滤、条件筛选、求和、最值)
- 模块化
学习目的
React全家桶
React全家桶 概念包含:
- React基础
- 其他的库使用:
- React-Router 路由库
- PubSub 消息管理库
- Redux 集中式状态管理库
- Ant-Design UI组件库(之一)
React入门
React是什么
什么是 React ?
React 是一个用于构建用户界面的 JavaScript 库。
- 是一个将数据渲染为 HTML 视图的开源 JS 库
- 它遵循基于组件的方法,有助于构建可重用的 UI 组件
- 它用于开发复杂的交互式的 web 和移动 UI
- 或者说:用于构建 Web 和 原生交互界面 的库
官网
强调:React只关注**界面**/或者叫**视图**
例如:展示信息需求
学习React前:
- 发送请求获取数据
- 处理数据(遍历、过滤、整理格式等)
- 通过js、jquary等,操作DOM呈现页面
学习React后:
- 发送请求获取数据
- 处理数据(遍历、过滤、整理格式等)
- 通过React,操作DOM呈现页面
React 的开发者?
React 的开发者是 Facebook ,且为开源生态
React 有什么特点?
- 声明式编码,组件化编码,提高开发效率&组件复用率
- 使用虚拟 DOM 而不是真正的 DOM
- 它可以用服务器渲染
- 它遵循单向数据流或数据绑定
- 高效(优秀的Diffing算法、使用虚拟 DOM 而不是真正的 DOM,尽量减少与真实DOM的交互)
React 的一些主要优点?
- 它提高了应用的性能(优秀的Diffing算法、使用虚拟 DOM 而不是真正的 DOM)
- 原生js操作DOM繁琐(原生js通过DOM-API来操作UI)、效率低
- 使用js直接操作DOM,浏览器会进行大量的重绘重排
- 原生js没有组件化/模块化编码方案,代码复用率低
- 可以方便在客户端和服务器端使用
- 可使用 React Native 做移动端开发,支持安卓和iOS
- 由于使用 JSX,代码的可读性更好
- 使用React,编写 UI 测试用例变得非常容易

React 使用步骤
- 使用react的步骤: 使用react需要先引入几个 react 包,核心库必须在扩展库前面引入!
- react.js (核心库):核心库要在react-dom之前引入
- react-dom.js :提供操作DOM的react扩展库
- babel.min.js:解析JSX语法代码转为JS代码的库,
- 即ES6==>ES5,解析import等;
- JSX==>JS,将 jsx 转为 js 的 babel 库(写的是JSX,浏览器只认js)
- 引入react库
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 先 引入react核心库,引入后,即全局添加了 React 对象,拥有各种API -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM,引入后,即全局添加了 ReactDOM 对象 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js (实例此处的这种引入方式,是告诉浏览器、交给浏览器来将jsx翻译为js,通过脚手架创建真实项目时,脚手架会附带翻译组件,翻译好再给浏览器)-->
<script type="text/javascript" src="../js/babel.min.js"></script>
/* 此处一定要写babel */
<script type="text/babel" >
你的JavaScript编码,写的是JSX,通过babel转js
</script>
</body>
- 然后在
<script type="text/babel" ></script>
里创建虚拟DOM
- 下述案例,数据写死,先直接写虚拟dom
<body>
<!-- 略:准备好一个“容器” -->
<!-- 略:先 引入react核心库,引入后,即全局添加了 React 对象 -->
<!-- 略:引入react-dom,用于支持react操作DOM,引入后,即全局添加了 ReactDOM 对象 -->
<!-- 引入babel,用于将jsx转为js (实例此处的这种引入方式,是告诉浏览器、交给浏览器来将jsx翻译为js,通过脚手架创建真实项目时,脚手架会附带翻译组件,翻译好再给浏览器)-->
<script type="text/babel" >
//1.创建虚拟DOM
const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
//2.渲染虚拟DOM到页面
// ReactDOM.render(虚拟DOM,容器)
ReactDOM.render(VDOM,document.querySelector(".test"))
</script>
</body>
- 注意⚠️:渲染不是一个叠加操作,而是覆盖操作
- 如果我创建好两个虚拟DOM后,渲染虚拟DOM到页面时写两个渲染语句,会触发覆盖,示例如下:
- 后续讲组件,通过组件完成多数据渲染
// 1.创建好虚拟DOM
const VDOM = <h1>React</h1> /* 此处一定不要写引号,因为不是字符串 */
const VDOM2 = <h1>尚硅谷</h1>
// 2.渲染虚拟DOM到页面的动作为覆盖操作,页面只会渲染生成 尚硅谷 的DOM操作,React被覆盖!
ReactDOM.render(VDOM,document.getElementById('test'))
ReactDOM.render(VDOM2,document.getElementById('test'))
- react开发者调试工具
- Chrome插件 React Developer Tool(注意安装来源为facebook的)
- 没写容器
<div id="test"></div>
,报错不是DOM element
- 创建的虚拟DOM中,加上了引号,页面中会变成字符串直出
- 引入babel的标签错写成js,报错语法错误
- 没写容器
hello react案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello_react</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 先 引入react核心库,引入后,即全局添加了 React 对象,拥有各种API -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel" > /* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
虚拟 DOM 和真实 DOM 的两种创建方法
- 为什么不用原生js,而改使用jsx来创建虚拟DOM?
- JS创建虚拟DOM太繁琐了,JSX更方便
JS 创建虚拟 DOM
- 语法:
- 创建真实DOM:
const VDOM=Document.createElement('h1',{id:'title'},React.createElement('span',{},'hello,React'))
- 创建虚拟DOM模板标签,创建嵌套格式的dom:
const VDOM=React.createElement(标签名(与真实属性一致写法,标签名使用单引号包裹),标签属性(写成对象可以放入多个属性),标签体内容)
- 创建嵌套格式的dom:
- 模板标签名(与真实属性一致写法,标签名使用单引号包裹),
- 模板标签属性(写成对象可以放入多个属性),
- 模板标签体内容(体现出原生JS 创建虚拟 DOM的弱点,虚拟/真实的标签的创建,还需要再嵌套一层DOM去创建)
- 创建真实DOM:
//0.创建真实DOM
const VDOM=Document.createElement('h1',{id:'title'},React.createElement('span',{},'hello,React'))
//1.创建虚拟DOM模板标签,创建嵌套格式的dom,嵌套两层
const VDOM=React.createElement('h1',{id:'title'},React.createElement('span',{},'hello,React'))
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
- 实际上,通过jsx写出来的模板标签,在经过浏览器翻译后,也还是回到js的写法,但是有了jsx,大大简化了编码的写法
- 本质:jsx是js的语法糖
JSX 创建虚拟DOM模板标签
- 优势:创建DOM时,不需要再嵌套一层操作获取dom的语法,写法上类似于直接写HTML,简化写虚拟DOM模板标签的操作
//1.创建虚拟DOM,通过添加小括号包裹,将HTML的dom结构,作为整体引入赋值
const VDOM = (
/* 此处一定不要写引号,因为不是字符串 */
<h1 id="title">
<span>Hello,React</span>
</h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
JS 的写法并不是常用的,常用JSX来写,毕竟JSX更符合书写的习惯
- 实际上,通过jsx写出来的模板标签,在经过浏览器翻译后,也还是回到js的写法,但是有了jsx,大大简化了编码的写法
- 本质:jsx是js的语法糖
使用jsx创建虚拟DOM案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1_使用jsx创建虚拟DOM</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 先 引入react核心库,引入后,即全局添加了 React 对象,拥有各种API -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel" > /* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = ( /* 此处一定不要写引号,因为不是字符串 */
<h1 id="title">
<span>Hello,React</span>
</h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
使用js创建虚拟DOM案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2_使用js创建虚拟DOM</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" >
//1.创建虚拟DOM
const VDOM = React.createElement('h1',{id:'title'},React.createElement('span',{},'Hello,React'))
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
虚拟DOM与真实DOM
- 关于虚拟DOM:
- 本质是Object类型的对象(一般对象)
- 虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM模板标签是React内部在用,无需真实DOM上那么多的属性。
- 即:虚拟DOM模板标签的标签的属性少于真实DOM
- 原生的真实DOM,身上有很多API,如改样式、拿值、拿状态等等,虚拟DOM不需要所有的标签属性
- 虚拟DOM模板标签最终会被React转化为真实DOM,呈现在页面上。
console.log('虚拟DOM',VDOM); //[Object Object]
console.log(typeof VDOM); //object
console.log(VDOM instanceof Object); //true
const TDOM = document.getElementById('demo')
console.log('虚拟DOM',VDOM); //[Object Object]
console.log('真实DOM',TDOM); //<div id="demo"></div>
debugger;
虚拟DOM与真实DOM区别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3_虚拟DOM与真实DOM</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<div id="demo"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel" > /* 此处一定要写babel */
//1.创建虚拟DOM
const VDOM = ( /* 此处一定不要写引号,因为不是字符串 */
<h1 id="title">
<span>Hello,React</span>
</h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
// 2.1对照渲染一个真实DOM
const TDOM = document.getElementById('demo')
console.log('虚拟DOM',VDOM);
console.log('真实DOM',TDOM);
// 借助打断点,在浏览器调试中,来查看真实标签的属性
debugger;
// console.log('虚拟DOM' VDOM);的打印结果为Object类型的对象(即:一般对象)
// console.log(typeof VDOM);打印数据类型,显示虚拟DOM的数据类型为:Object
// console.log(VDOM instanceof Object);打印数据类型是否为Object类型,显示打印结果为:true
// console.log('真实DOM',TDOM);的打印结果为: DOM元素的HTML标签结构,如此处打印的结果为:<div id="demo"></div>
/*
关于虚拟DOM:
1.本质是Object类型的对象(一般对象)
2.虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。即:虚拟DOM的标签的属性少于真实DOM
3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上。
*/
</script>
</body>
</html>
JSX语法/JSX模板标签语法
定义:
- 全称:JavaScript XML
- 是react定义的、一种类似于XML的JS扩展语法:JS + XML
- XML为早期存储和传输数据的一种格式,类似于HTML,后期被JSON取代(减少了标签结构的使用+方便存储和读取)
- JS内置有JSON对象的两个方法:JSON.parse用于将JSON字符串快速解析为对应的数组和对象(读取);JSON.stringfy用于将JS中的数组和对象转成JSON字符串(存储)
- 本质是js下的创建虚拟DOM方法语句React.createElement(component,props,...children)方法的语法糖
- 作用:用于简化创建虚拟DOM
- 写法:
var ele = <h1>Hello JSX</h1>
- 注意1:JSX不是字符串,也不是HTML/XML标签
- 注意2:JSX作为JS的语法糖,最终翻译产生的就是一个JS对象
- 写法:
- 标签名任意:HTML标签或其他标签
本质:类似于VUE的模板语法,下述我将其称为模板标签
JSX语法规则
- 创建虚拟DOM
- 定义虚拟DOM模板标签,不能使用引号
“”
(多级结构不是字符串,不能用引号)- 可以使用括号
()
作多级模板标签结构包裹
- 可以使用括号
- 模板标签中混入JS表达式的时候使用
{}
- 例如通过变量形式读取,读取时支持使用表达式
- 如,使用toLowerCase()方法,可读取并转化成小写输出
- 定义虚拟DOM模板标签,不能使用引号
// 1.创建虚拟DOM(多级结构)
const VDOM = (
// 2.混入JS表达式的时候使用`{}`
<h2 id={myId.toLowerCase()}>
<span>{myData.toLowerCase()}</span>
</h2>
)
- 虚拟DOM下,模板标签中的样式
- CSS样式的类名指定不能使用class,使用
className
去指定类名(class是ES6中类定义的关键字,为了避免冲突而使用className)- 所指定的CSS样式的类名,和JS中类名一致,使用引号
- 内联样式要使用
{{}}
包裹,语法为style={{key:value}}
- fontSize这种属性要写小驼峰,如
style={{color:‘white’,fontSize:20px}}
- 通过使用
{{}}
,即通过对象,来表达多种{key:value}对象,外面包一层{}代表其中的为js表达式
- fontSize这种属性要写小驼峰,如
- CSS样式的类名指定不能使用class,使用
const VDOM = (
<div>
// 1.CSS样式的类名指定使用`className`
<h2 className="title" id={myId.toLowerCase()}>
// 2.虚拟DOM下,标签中的样式要使用`{{}}`包裹,例如以下<span>标签中的样式
<span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
</div>
)
- 虚拟DOM下的模板标签规范
- 模板标签不能有多个根标签,必须只能有一个根标签
- 可以在外层再包裹一个容器
- 模板标签必须闭合,自闭合也行,如
<input type="test" />
- jsx的模板标签语法,会被浏览器转换为js和html,当首字母
(1)若小写字母开头,则会转为 html5中的同名元素,如果 html 中无该标签对应的元素,就报错 (2)若大写字母开头,react 就认为是组件,就去渲染对应的组件,若该大写字母开头的组件没有定义,则报错
const VDOM = (
<div>
// 模板标签不能有多个根标签,例如有两个h2根标签,在外层再嵌套一个包裹一个div容器
<h2 className="title" id={myId.toLowerCase()}>
<span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
<h2 className="title" id={myId.toUpperCase()}>
<span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
// 模板标签必须闭合,自闭合也行,或者加上结束标签
<input type="text"/>
</div>
)
- jsx语法规则案例
jsx语法规则案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsx语法规则</title>
<style>
.title{
background-color: orange;
width: 200px;
}
</style>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel" >
const myId = 'aTgUiGu'
const myData = 'HeLlo,rEaCt'
//1.创建虚拟DOM
const VDOM = (
<div>
<h2 className="title" id={myId.toLowerCase()}>
<span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
<h2 className="title" id={myId.toUpperCase()}>
<span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span>
</h2>
<input type="text"/>
</div>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
/*
jsx语法规则:
1.定义虚拟DOM时,不要写引号。
2.标签中混入JS表达式时要用{}。
3.样式的类名指定不要用class,要用className。
4.内联样式,要用style={{key:value}}的形式去写。
5.只有一个根标签
6.标签必须闭合
7.标签首字母
(1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
*/
</script>
</body>
</html>
JSX 模板标签中的变量、表达式、语句
需求:根据动态数据,生成
li
理解:vue中的v-for
- 在react的模板标签中,不需要写vue中的v-for,数组变量会自动展开遍历
JSX会以数组形式自动拆解、遍历模板标签中的变量:
- 如变量为数组,会自动展开遍历
- 数组变量返回的内容,作为js表达式/html结构,如果返回的数据是包含结构的,自动展开并填入模板标签后自动生效
- 如数组中只有数据,则此时需要在JSX模板标签中写js表达式来遍历,返回
标签结构+赋值
的数据,才能填入模板标签作为模板生效 - 每一个变量/child节点,都必须要有唯一的key属性(属性名为key的属性且值是唯一的,如简单场合下使用index索引值区分)
- 如变量为对象,则会报错
- 对象类型不能作为react的child,不能作为react的合法的节点,无法遍历
- 如变量为数组,会自动展开遍历
JSX 模板标签中的变量、表达式、语句
- 可以在JSX的模板标签中写变量和表达式
- 会以数组形式,自动拆解、遍历JSX模板标签中的变量
- 每一个变量/child节点,都必须要有唯一的key属性(属性名为key的属性且值是唯一的,如简单场合下使用index索引值区分)
- 不支持在JSX的模板标签中写语句
- 不支持在JSX的模板标签中写for循环、if判断等js语句
- 可以在JSX的模板标签中写变量和表达式
一定注意⚠️区分:【js语句(代码)】与【js表达式】
JSX 模板标签支持变量和表达式
- 表达式的定义:一个表达式会产生一个值,可以放在任何一个需要值的地方
- 表达式可以拿变量去接
下面这些都是表达式:
- a
- a+b
- demo(1)
- arr.map()
- function test () {} 函数表达式,可以拿变量接返回值
不支持语句(代码)
下面这些都是语句(代码):
if(){}
for(){}
switch()
const data = ['A','B','C']
const VDOM = (
<div>
<ul>
{
data.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
ReactDOM.render(VDOM,document.getElementById('test'))
JSX语法注释规则
- 注释是写在花括号里
ReactDOM.render(
<div>
<h1>小丞</h1>
{/*注释...*/}
</div>,
document.getElementById('example')
);
JSX语法中的数组
- JSX 允许在模板中插入数组,数组自动展开全部成员
var arr = [
<h1>小丞</h1>,
<h2>同学</h2>,
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('example')
);
需求案例:根据动态数据,生成 `<li>`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsx小练习</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel" >
/*
一定注意区分:【js语句(代码)】与【js表达式】
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
下面这些都是表达式:
(1). a
(2). a+b
(3). demo(1)
(4). arr.map()
(5). function test () {}
2.语句(代码):
下面这些都是语句(代码):
(1).if(){}
(2).for(){}
(3).switch(){case:xxxx}
*/
// 以数组格式,模拟一些数据,赋值给变量
const data = ['Angular','React','Vue']
// 如果后台返回的变量,数据格式是数组,且带结构的
const data2 = [<li>Angular</li>,<li>React</li>,<li>Vue</li>]
// 对象类型不能作为react的child,不能作为react的合法的节点,无法遍历
//1.创建虚拟DOM
const VDOM = (
<div>
<h1>前端js框架列表</h1>
<ul>
{/* map遍历变量,取出数组,返回结构+赋值 */}
{
data.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
<ul>
{/* 如果后台返回的变量,数据格式是数组,且带结构的,则在渲染时不需要写js遍历,直接放入变量,会自动拆解变量遍历 */}
{data2}
{/* 不支持对象类型,对象不能作为react的合法的节点,无法遍历 */}
</ul>
</div>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>
</body>
</html>
总结
- 理解:vue中的v-for;在react的模板标签中,不需要写vue中的v-for,数组变量会自动展开遍历
- JSX会以数组形式自动拆解、遍历模板标签中的变量
- 如变量为数组,会自动展开遍历;
- 如变量为对象,则会报错(对象类型不能作为react的child合法的节点)
- 数组变量返回的内容,作为js表达式/html结构,如果返回的数据是包含结构的,自动展开并填入模板标签后自动生效
- 如数组中只有数据,则此时需要在JSX模板标签中写js表达式来遍历,返回
标签结构+赋值
的数据,才能填入模板标签作为模板生效- 每一个变量/child节点,都必须要有唯一的key属性(属性名为key的属性且值是唯一的,如简单场合下使用index索引值区分)
- 可以在JSX的模板标签中写变量和表达式,并会以数组形式,自动拆解、遍历JSX模板标签中的变量
- 不支持在JSX的模板标签中写for循环、if判断等js语句