React 基础
整体介绍
内容介绍
-
React 概述
-
JSX
-
React 组件基础
React 介绍
目标
了解react的基本概念,
是什么
React 是用于构建用户界面的 JavaScript 库
- 构建用户界面. User Interface,对咱们前端来说,简单理解为:HTML 页面
- javscrtipt库。不是框架,是库。
- vue: 是渐进式的javascript框架
- react 全家桶是框架
- react: 核心库
- react-dom: dom操作
- react-router:路由,
- redux:集中状态管理
拓展
- 框架背景
- react是Facebook(meta) 内部项目
- vue是尤雨溪个人作品
- angular是goole公司产品
- 趋势
- react全球第一
- vue在国内较多,react也慢慢多了
- angular在跨国公司使用较多
小结
react是?构建用户界面的js库。
React 特点
目标
了解react的特点
声明式
只需要描述UI看起来时什么样的,就跟写html一样。
用类似于html的语法来定义页面。react中通过数据驱动视图的变化,当数据发生改变react能够高效地更新并渲染DOM。
<div className="app">
<h1>Hello React! 动态数据变化:{count}</h1>
</div>
组件化
组件是react中最重要的内容
组件用于表示页面中的部分内容
组合、复用多个组件,就可以实现完整的页面功能
学习一次,随处使用
使用react/rect-dom可以开发Web应用
使用react/react-native可以开发移动端原生应用(react-native)RN
使用react可以开发VR(虚拟现实)应用(react/react360)
小结
从你的角度看 React 特点:工资高、大厂必备(阿里,字节,百度、腾讯、京东、蚂蚁金服、拼多多、美团、外企、银行等都在用)
react的三个特点:
- 声明式
- 组件化
- 一次学习多次使用
React脚手架-从零开始创建项目
目标
掌握react脚手架的使用
脚手架create-react-app
官方工具: create-react-app
创建方式1
-
先全局安装脚手架工具包
命令:
npm i -g create-react-app
-
用脚手架工具来创建项目
命令:
create-react-app your-project-name
创建方式2
直接使用npx来创建项目
命令:
npx create-react-app your-project-name
解释:
- npx create-react-app 是固定命令,
create-react-app
是 React 脚手架的名称 - your-project-name 表示项目名称,可以修改
拓展
-
npx
是 npm v5.2 版本新添加的命令,用来简化 npm 中工具包的使用 -
没有npx之前:
- 全局安装npm i -g create-react-app
- 在通过脚手架的命令来创建 React 项目
-
有了npx之后
npx 调用最新的 create-react-app 直接创建 React 项目
React脚手架-了解项目的工作方式
目标
认识react项目目录结构
启动项目
npm start
目录src
说明:
src
目录是我们写代码进行项目开发的目录- index.js是入口文件
- 查看
package.json
两个核心库:react
、react-dom
(脚手架已经帮我们安装好,我们直接用即可)
调整
-
删除 src 目录下的所有文件
-
创建src/index.js, 内容如下:
console.log('我的第一个react项目跑起来啦')
查看效果
在浏览器控制台中查看效果
工作原理
webpack会实时自动打包,并把代码嵌入到public/index.html
文件中,并执行。
小结
-
我们在哪里写代码?
-
入口文件是?
第一份react程序
目标
了解react程序的基本步骤
步骤
- 导入包: React, ReactDOM
- 创建 react元素
- 渲染元素到某个dom上
示例
在页面上创建一个h1标题。
代码:index.js
// 导入react和react-dom
import React from 'react'
import ReactDOM from 'react-dom'
// 创建元素
const title = React.createElement('h1', {id:'box'}, 'hello react')
// 渲染react元素
ReactDOM.render(title, document.getElementById('root'))
效果:
在浏览器中查看
理解react-dom
rect包 提供必要功能来定义react组件。
react-dom包用来将react组件渲染到dom中。
react-native包 用来将react组件渲染到IOS和Android程序中。
package.json
小结
react包的作用是?
react-dom包的作用是?
一个react程序的三个步骤是?
练习
目标
用脚手架工具创建一个名为react-demo
的项目,并在页面上渲染如下dom结构
<div>
<h1>
第一个react程序
</h1>
<p>
react是用来构建用户界面的js库
</p>
</div>
要点
React.createElement的格式:
React.createElement('标签名',{标签上的属性1:值1},子元素1,子元素2)
参考
https://zh-hans.reactjs.org/docs/react-api.html#createelement
JSX介绍-基本使用
问题导入
createElement的效率太低了。
- 繁琐不简洁
- 不直观,无法一眼看出所描述的结构
- 不优雅,开发体验不好
目标
了解JSX的定义,了解它的工作过程
JSX是什么
JSX:是 JavaScript XML的缩写。
-
在 JS 代码中书写 XML 结构
- 注意:JSX 不是标准的 JS 语法,是 JS 的语法扩展。脚手架中内置了 @babel/plugin-transform-react-jsx 包,用来解析该语法。
-
React用它来创建 UI(HTML)结构
理解:我们之前用html写页面,现在是用jsx来写页面
jsx示例
// 导入react和react-dom
import React from 'react'
import ReactDOM from 'react-dom'
// jsx创建元素
const list = <ul><li>html</li><li>js</li><li>css</li><ul>
// 渲染react元素
ReactDOM.render(list, document.getElementById('root'))
优势
- 采用类似于 HTML 的语法,降低了学习成本,会 HTML 就会 JSX
- 充分利用 JS 自身的能力来创建 HTML 结构。比如,利用 JS 数组的 map 方法创建列表结构
拓展:JSX是如何工作的?
jsx —babel—> React.createELement
小结
- jsx是什么的简写?
- jsx的作用是?
- jsx相比createElement的好处?
- 为啥在js代码中可以直接写jsx的代码?
JSX的注意事项
目标
掌握JSX的5个注意事项
内容
- jsx必须要有一个根节点
- 属性名不能用js中的关键字。例如class, for
- 单标签要闭合
- 换行建议使用( )包裹
- 老版本(16.8)先引入react才能使用jsx
jsx必须要有一个根节点
虚拟根节点
有两种格式
格式1:<> xxx </>
import ReactDOM from 'react-dom'
const title = <> <h1>Hello React</h1><p>p标签</p> </>
ReactDOM.render(title, document.querySelector('#root'))
格式2:<React.Fragment> xxx </React.Fragment>
import ReactDOM from 'react-dom'
const title = <React.Fragment> <h1>Hello React</h1><p>p标签</p> </React.Fragment>>
ReactDOM.render(title, document.querySelector('#root'))
属性名不能用js中的关键字
例如class, for
- class -> className
- for ->htmlFor
单标签要闭合
<input>
—><input />
老版本(16.8)先引入react才能使用jsx
理解引入react的作用(提供createElement的功能)
老版本中不引入就会报错React must be in scope when using JSX
换行建议使用()包裹
const content = (
<div>
<h1>xxx</h1>
</div>
)
JSX-嵌入表达式
导入
通过上面的学习,我们已经可以使用jsx来描述一段静态结构了,更多的情况下,我们需要动态的结构。例如,在页面上输出一个随机值
import ReactDOM from 'react-dom'
const num = Math.random()
const title = (<div>
随机值:num
</div>)
ReactDOM.render(title, document.querySelector('#root'))
目标
会在 JSX中嵌入表达式
嵌入表达式的格式
{ JS 表达式 }
例如:
import ReactDOM from 'react-dom'
const num = Math.random()
const title = (<div>
随机值:{ num }
</div>)
ReactDOM.render(title, document.querySelector('#root'))
大括号是一种特殊的语法,让 JSX 解析器知道它需要将它们之间的内容解释为 JavaScript代码 而不是字符串
作用:执行{}内部的代码,并输出结果。
嵌入表达式的位置
-
属性值
const logo = 'https://create-react-app.dev/img/logo.svg' <img width="80" src={logo} />
-
内容
const name = '小芳' <div>{name}</div>
单花括号中可以写什么?
可以写
-
表达式
定义:数据类型和运算符的组合(可以单独出现数据类型,也可以数据类型+运算符的组合)
特点:有值(或者能够计算出一个值); 能被console.log()
-
其他的jsx表达式
-
注释
不可以写
- 对象
- js语句:if 语句/ switch-case 语句/ 变量声明语句
示例
import React from 'react'
import ReactDOM from 'react-dom'
const girl = {
name: '小芳',
age: 19,
logo: 'https://create-react-app.dev/img/logo.svg',
skills: ['唱歌', '收稻子']
}
const f1 = () => {
return <i>{girl.skills.join(',')}</i>
}
const baseInfo = (
<div>
姓名: {girl.name}
妙龄: {girl.age}
</div>
)
const content = (
<div style={{ padding: 50 }}>
<h1>jsx-表达式</h1>
{/* 1. {} 可以用在内容上 */}
{/* {}可以包其他的jsx */}
{baseInfo}
{/* {}可以包表达式 */}
<p>爱好:{girl.skills}</p>
<p>字符串:{'abc'}</p>
<p>字符串:{'{'}</p>
<p>数组:{[1, 2, 3]}</p>
<p>数值:{100}</p>
<p>函数:{f1()}</p>
<p>算数表达式:100/2={100 / 2}</p>
<p>
三元表达式:{girl.age < 28 ? '芳龄' : '年龄'} {girl.age}
</p>
{/* 2. {}可以用在属性值上 */}
<p className={['class1', 'class2'].join(' ')}>类名组合</p>
<img width="80" src={girl.logo} />
{/*
下面是错误的示范
不能输出对象,不能使用语句
<p>{{ a: 1 }}</p>
<p>{var a =1 }</p> */}
</div>
)
ReactDOM.render(content, document.getElementById('root'))
小结
- {}的作用是?
- {}可以嵌入在哪里?
- {}内部可以写什么,不可以写什么?
JSX-条件渲染
目标
掌握条件渲染,能根据是否满足条件生成 HTML 结构
实现方式
if/else
- 三元运算符
- 逻辑与(&&)运算符
- switch case
示例
简单情况-用三元表达式
const flag = 0
const content = (<div>{flag ? '达成' : '没有达成'}</div>)
简单情况-用逻辑与
const isLogin = true
const content = (<div>{ isLogin && '您登录了'}</div>)
复杂情况-使用额外的函数
const loadData = (isLoading) => {
if (isLoading) {
return <div>数据加载中,请稍后...</div>
} else {
return <div>数据加载完成,此处显示加载后的数据</div>
}
}
const content = <div>{loadData(true)}</div>
小结
简单条件渲染使用________ 和 _____
复杂的条件渲染使用函数,在函数内部通过if,else,swich, case来显示内容
JSX-列表渲染
目标
在JSX中使用数组的map方法来生成列表结构
场景
从后端取回来的数据保存在数组中,需要用列表展示。这里的数组如下:
const skills = [
{ id: 1, name: 'html' },
{ id: 2, name: 'css' },
{ id: 3, name: 'js' }
]
我们要生成的dom结构如下:
<ul>
<ol>技能1:html</ol>
<ol>技能2:css</ol>
<ol>技能3:js</ol>
</ul>
如何实现呢?
笨方法
直接定义一个数组,每个元素都是一个jsx结构
const skills = [<ol>技能1:html</ol>, <ol>技能2: css</ol>, <ol>技能3: js</ol>]
const content = <ul>{skills}</ul>
ReactDOM.render(content, document.getElementById('root'))
用map
完整格式
// 完整格式
const t = skills.map(function(item) {
return <ol>技能{item.id}: {item.name}</ol>
})
const list = <ul>{t}</ul>
简写格式
const list = (
<ul>
{skills.map(item => <ol>技能{item.id}: {item.name}</ol>)}
</ul>
)
小结
作用:重复生成相同的 HTML 结构。
列表渲染中的key
目标
了解key的作用,能正确给循环渲染项添加key
了解key的作用
React 内部用来进行性能优化时使用的,在最终的HTML结构中是看不到的。
性能优化
例如,数据如下
const songs = [
{ id: 1, name: '痴心绝对' },
{ id: 2, name: '像我这样的人' },
{ id: 3, name: '南山南' }
{ id:4, name: 'abc'}
]
生成的dom
<ul>
<li>排名:1 - 歌名:痴心绝对</li>
<li>排名:2 - 歌名:想我这样的人</li>
<li>排名:3 - 歌名:南山南</li>
</ul>
如果添加一条数据,则视图也要随之更新,而更新的逻辑是:前三条正常保留,而重新添加第四条。
如何设置key
如果数据中有一个唯一的属性值,就可以使用这个属性来当做key
如果没有,就可以用索引值
练习-用jsx来写结构
目标
按要求完成列表渲染
内容
// 下面是数据
const list = [
{ id: 1, name: '武汉黑马前端64期', salary: 11000 },
{ id: 2, name: '武汉黑马前端66期', salary: 15000 }
]
// 下面是要求生成的结构
/*
<ul>
<li>
<h3>班级:武汉黑马前端64期</h3>
<p>工资:11000</p>
</li>
<li>
<h3>班级:武汉黑马前端66期</h3>
<p>工资:15000</p>
</li>
</ul>
*/
JSX 样式处理
目标
掌握在jsx中使用行内样式和类名样式
行内样式 - style
格式
<dom元素 style={ {css属性1:值1,css属性2:值2} }></dom元素>
示例
// 行内样式
<h1 style={ {color: 'red', width: 200, backgroundColor: 'black'} }>
我是黑底红字的h1
</h1>
要点:
- 为啥有两个{{ }}
- 外层的{}表示 要开始写js了
- 内层的{}表示是一个对象
- 属性名是小驼峰格式 (background-color ===> backgroundColor)
- 属性值是字符串, 如果单位是px,可以简写数值
使用 className
要点
- 用className(不是class)定义类名
- 把样式写在额外的.css文件中,然后引入.css文件
import './index.css'
// 类名
<h1 className="title">
我是黑底红字的h1
</h1>
补充建立.css
.title{
color: red;
width: 200px;
background-color: black;
}
小结
jsx中的样式:
- 行内: style={{对象,小驼峰}}
- 外部: className
JSX 整体总结
- React 使用 JSX 来编写 UI(HTML)
- React 完全利用 JS 语言自身的能力来增强 UI 的编写 - 能用 JS 来实现的功能绝不会增加一个新的 API
- 现在,就可以使用 React 来编写任意 UI 结构了
案例
目标
综合使用jsx的知识,用给定的数据+基本结构和样式渲染成如下效果。
导入本地图片
<img src="./images/avater.png"
不一定能被脚手架工具处理。
如果发现显示不出来,就
import avatar from './images/avatar.png'
<img src={avatar }/>
参考代码
import ReactDOM from 'react-dom'
import './index.css'
import avatar from './images/avatar.png'
// 任务
// 下面有一份数据,需要渲染到页面上
const state = {
// hot: 热度排序 time: 时间排序
tabs: [
{
id: 1,
name: '热度',
type: 'hot'
},
{
id: 2,
name: '时间',
type: 'time'
}
],
active: 'time',
list: [
{
id: 1,
author: '刘德华',
comment: '给我一杯忘情水',
time: '2021-10-10 09:09:00',
img:
'https://y.qq.com/music/photo_new/T001R300x300M000003aQYLo2x8izP.jpg?max_age=2592000',
// 1: 点赞 0:无态度 -1:踩
attitude: 1
},
{
id: 2,
author: '周杰伦',
comment: '听妈妈的话',
time: '2021-10-11 09:09:00',
img:
'https://y.qq.com/music/photo_new/T001R500x500M0000025NhlN2yWrP4.jpg?max_age=2592000',
// 1: 点赞 0:无态度 -1:踩
attitude: 0
},
{
id: 3,
author: '陈奕迅',
comment: '十年',
time: '2021-10-11 10:09:00',
img:
'https://y.qq.com/music/photo_new/T001R500x500M000003Nz2So3XXYek.jpg?max_age=2592000',
// 1: 点赞 0:无态度 -1:踩
attitude: -1
}
]
}
const element = (
<div className="App">
<div className="comment-container">
{/* 评论数 */}
<div className="comment-head">
<span>{state.list.length} 评论</span>
</div>
{/* 排序 */}
<div className="tabs-order">
<ul className="sort-container">
{state.tabs.map((item) => (
<li
className={item.type === state.active ? 'on' : ''}
key={item.id}>
按{item.name}排序
</li>
))}
{/* <li className="on">按 热度 排序</li>
<li>按 时间 排序</li> */}
</ul>
</div>
{/* 添加评论 */}
<div className="comment-send">
<div className="user-face">
<img className="user-head" src={avatar} alt="" />
</div>
<div className="textarea-container">
<textarea
cols="80"
rows="5"
placeholder="发条友善的评论"
className="ipt-txt"
/>
<button className="comment-submit">发表评论</button>
</div>
<div className="comment-emoji">
<i className="face" />
<span className="text">表情</span>
</div>
</div>
{/* 评论列表 */}
<div className="comment-list">
{state.list.map((item) => (
<div key={item.id} className="list-item">
<div className="user-face">
<img className="user-head" src={item.img} alt="" />
</div>
<div className="comment">
<div className="user">{item.author}</div>
<p className="text">{item.comment}</p>
<div className="info">
<span className="time">{item.time}</span>
{/* 喜欢 */}
<span className={item.attitude === 1 ? 'like liked' : 'like'}>
<i className="icon" />
</span>
{/* 不喜欢 */}
<span className={item.attitude === -1 ? 'hate hated' : 'hate'}>
<i className="icon" />
</span>
<span className="reply btn-hover">删除</span>
</div>
</div>
</div>
))}
</div>
</div>
</div>
)
ReactDOM.render(element, document.getElementById('root'))
练习
拓展1-环境配置-引入eslint
目标
在react项目中配置eslint,并启用保存自动格式化功能
思路
- 在项目中安装eslint
- 用eslint的init命令创建eslint配置文件
- 设置vscode的自动保存格式化
步骤
-
npm i eslint typescript -D
-
在项目根目录,运行
npx eslint --init
- 按交互提示安装相关插件
- 选择是否使用 TypeScript, 选择是
- 它会自动生成eslint的配置文件
- 按交互提示安装相关插件
-
设置vscode的自动保存格式化
代码
在项目根目录下,补充配置文件:.vscode\settings.json
,其内容如下:
{
"eslint.run": "onType",
"eslint.options": {
"extensions": [".js", ".vue", ".jsx", ".tsx"]
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
拓展2-环境配置-引入prettier-now
eslint并不能深入到jsx代码中来格式化,所以需要额外的工具。
prettier-now
是prettier项目的分支,具备和prettier一样的功能,不过,它允许使用更多的配置项。在vscode的插件库中,同时有prettier-now和prettier,在安装时,请不要安装错了。
步骤
- 安装vscode插件
prettier-now
- 补充配置
代码
.vscode\settings.json
{
"eslint.run": "onType",
"eslint.options": {
"extensions": [".js", ".vue", ".jsx", ".tsx"]
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
// 编辑器设置 - 保存时做格式化
"editor.formatOnSave": true,
// 编辑器设置 - 默认采用prettier-now做格式化
// 如果使用的是prettier,这的设置应该是 esbenp.prettier-vscode
"editor.defaultFormatter":"remimarsal.prettier-now",
// 控制缩进
"prettier.useTabs": false, // 缩进不使用tab,使用空格
"prettier.tabWidth": 2, // 缩进字节数
// 函数声明时小括号前后要加空格
// 如果你使用prettier这一项是不能做选择的,导致和eslint默认配置的冲突
// 可以在百度中搜到很多的记录: https://www.baidu.com/s?wd=prettier%20%E5%87%BD%E6%95%B0%E7%A9%BA%E6%A0%BC
"prettier.spaceBeforeFunctionParen": true,
// react的jsx让>与结束标签同行
"prettier.jsxBracketSameLine": true,
"prettier.bracketSpacing": false, // 去掉数组内部前后的空格
"prettier.semi": false, // 不要给语句加;
"prettier.singleQuote": true, // 采用单引号
"prettier.trailingComma": "none", // 不要尾随逗号,
"prettier.printWidth": 80, // 每行超过80列就换行
// 在.js中,写div按下tab就可以自动补全,而不需要写<div再补全
"emmet.includeLanguages": {
"javascript": "javascriptreact"
}
}
react 17之后,页面上使用jsx时,可以省略import React
在16的版本中,页面上使用jsx,必须import react