## 01-react概述
[react是什么]()
`React`是一个用于构建用户界面的`JavaScript库`。
用户界面: HTML页面(前端)
React主要用来写HTML页面,或`构建Web应用`
如果从MVC的角度来看, React仅仅是视图层(V ) , 也就是只负责视图的渲染,而并非提供了
完整的M和C的功能。
[react的特点]()
+ 声明式
+ 基于组件
+ 学习一次,随处使用
**声明式**
只需要描述UI(HTML)是什么样,React负责渲染UI,并在数据变化时更新UI
```js
const jsx = <div className="app">
<h1>React动态变化:{count}</h1>
</div>
```
**基于组件**
+ 组件时React`最重要`的内容
+ 组件表示页面中的部分内容
+ 组合、复用多个组件,可以实现完成的页面功能
**学习一次,随处使用**
+ 使用React可以开发Web应用
+ 使用React可以开发移动端原生应用( react-native )
+ 使用React可以开发VR(虚拟现实)应用(react360)
[react的基本使用]()
**React的安装**
安装命令:npm i react react-dom
+ react 包是核心,提供创建元素、组件等功能
+ react-dom 包提供DOM相关功能等
**React的使用**
1、引入react和react-dom 两个js文件
```html
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
```
2、创建React元素
```js
<script>
const title = React.createElement('h1',null,'Hello React')
</script>
```
3、渲染React元素
```js
ReactDOM.render(title,document.getElementById('root'))
```
方法说明:
React.createElement
参数1:元素名称
参数2:元素属性
参数3...:元素的子节点(文本、标记...)
ReactDOM.render
参数1:要渲染的React元素
参数2:DOM,渲染的挂载位置
【案例:实现多个元素嵌套显示】
## 02-react脚手架
**React脚手架意义**
1. 脚手架是开发现代Web应用的必备。
2. 充分利用Webpack、 Babel、 ESLint等I具辅助项目开发。
3. 零配置,无需手动配置繁琐的工具即可使用。
4. 关注业务,而不是工具配置。
**使用React脚手架初始化项目**
1、初始化项目,命令:npx create-react-app 项目名称( my-app)
2、启动项目,在项目根目录执行命令:npm start (yarn start)
**npx命令介绍**
+ npm v5.2.0 引入的一 条命令
+ 目的:提升包内提供的命令行工具的使用体验
+ 以前:先安装脚手架包,再使用这个包中提供的命令
+ 现在:无需安装脚手架包,就可以直接使用这个包提供的命令
**补充:**
1.推荐使用: npx create-react-app my-app
2.npm init react-app my-app
3.yarn create react- app my-app
+ yarn 是Facebook发布的包管理器,可以看做是npm的替代品,功能与npm相同
+ yarn具有快速、可靠和安全的特点
+ 初始化新项目: yarn init
+ 安装包: yarn add包名称
+ 安装项目依赖项: yarn
+ 其他命令,请参考yarn文档
**在脚手架中使用React**
1.导入react和react-dom两个包。
```js
import React from 'react'
import ReactDOM from 'react-dom'
```
2.调用React.createElement(方法创建react元素。
3.调用ReactDOM.render(方法渲染react元素到页面中。
react基础阶段总结
1. React是构建用户界面的JavaScript库
2. 使用react时,`推荐使用脚手架方式`。
3. 初始化项目命令: `npx create-react-app my-app`。
4. 启动项目命令: `yarn start` (或`npm start` )。
【案例】(关于模块化知识的使用)外部组件的定义
## 03-JSX的基本使用
createElement的问题:
1.繁琐不简洁。
2.不直观,无法一眼看出所描述的结构。
3.不优雅,用户体验不爽。
**JSX简介**
JSX是JavaScript XML的简写,表示在JavaScript代码中写XML ( HTML )格式的代码。
优势:声明式语法更加直观、与HTML 结构相同,降低了学习成本、提升开发效率
JSX使用步骤
1、使用JSX语法创建react元素
```js
const title = <h1>Hello JSX</h1>
```
2、使用ReactDOM.render() 方法渲染react元素到页面
```js
ReactDOM.render(title,root)
```
**为什么脚手架中可以使用JSX语法**
1. JSX不是标准的ECMAScript语法,它是`ECMAScript的语法扩展`。
2. 需要使用`babel`编译处理后,才能在浏览器环境中使用。
3. create-react-app脚手架中已经默认有该配置,无需手动配置。
4. 编译JSX语法的包为: @babel/preset-react。
**JSX的注意点**
1. React元素的属性名使用`驼峰命名法`
2. 特殊属性名: class -> `className`、for -> htmlFor、tabindex -> tabIndex
3. 没有子节点的React元素可以用` />` 结束
4. 推荐:使用`小括号包裹JSX`,从而避免JS中的自动插入分号陷阱
**在JSX中使用JavaScript表达式**
+ 数据储存在JS中
+ 语法:`{JavaScript表达式}`
**JSX的条件渲染**
+ 场景:loading效果
+ 条件渲染:根据条件渲染特定的JSX结构
+ 可以使用`if/else`或`三元运算符`或`逻辑与运算符`来实现
**JSX的列表渲染**
+ 如果要渲染一组数据,应该使用数组的`map()`方法
+ 注意:渲染列表时应该添加key属性,`key属性的值要保证唯一`
+ 原则: `map()`遍历谁,就给谁添加key属性
+ 注意:`尽量避免使用索引号作为key`
```js
const students = [
{id:1,name:'张三'},
{id:2,name:'李四'},
{id:3,name:'王五'},
]
const list = {
<ul>
{students.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
}
```
**JSX的样式处理**
1、行内样式-style
```js
<h1 style={{color:'red',backgroundColor:'blue'}}> JSX行内样式 </h1>
```
2、类名-className(推荐)
需要引入css
```js
import './css/index/css'
```
【案例:将指定json数据渲染至网页中】
```
fetch(url)
.then(response => { response.json(()=>{}).then(...).then(...) })
```
**JSX阶段总结**
1. JSX React的核心内容。
2. JSX 示在JS代码中写HTML结构,是React声明式的体现。
3. 使用JSX配合嵌入的JS表达式、条件渲染、列表渲染,可以描述任意UI结构。
4. 推荐使用className的方式给JSX添加样式。
5. React 完全利用JS语言自身的能力来编写UI ,而不是造轮子增强HTML功能。
## 04-React组件介绍
+ 组件是React的`一等公民`,使用React就是在用组件
+ 组件表示React实现的部分功能
+ 组合多个组件实现完整的页面功能
+ 特点:可复用、独立、可组合
##### 组件的两种创建方式(1函数组件)
+ 函数组件:使用JS的函数(或箭头函数)创建的组件
+ 注意:函数名称必须以`大写字母开头`
+ 注意: 函数组件必须有`返回值`,表示该组件的结构
+ 注意:返回值为null,就不显示任何内容
```js
function Hello(){
return (
<div>函数组件</div>
)
}
```
+ 渲染函数组件:用函数名作为组件标签名
+ 组件标签可以是单标签,也可以是双标签
```js
ReactDOM.render(<Hello />,root)
```
##### 组件的两种创建方式(2类组件)
+ 类组件:使用ES6的class创建的组件
+ 注意:类名称必须以`大写字母开头`
+ 注意:类组件应该继承`React.Component` 父类,从而可以使用父类中提供的方法或者属性
+ 注意:类组件必须提供`render()`方法
+ 注意:render() 方法必须用`return返回值`,表示该组件的结构
```js
class Hello extends React.Component{
render(){
return <div>Hello Class Component!</div>
}
}
ReactDOM.render(<Hello />,root)
```
##### 组件的两种创建方式(3抽离为独立js文件)
1、创建Hello.js
2、在Hello.js中导入React
3、创建组件(函数 或 类)
4、在Hello.js 中导出该组件
5、在index.js 中导入Hello 组件
6、渲染组件
```js
import React from 'react'
class Hello extends React.Component{
render(){
return <div>Hello Class Component!</div>
}
}
export default Hello
```
##### React事件处理(1事件绑定)
+ React事件绑定语法与DOM事件语法很相似
+ 语法: `on+事件名称 = {事件处理程序}`,比如:onClick = {()=>{}}
+ 注意:`React事件采用驼峰法命名`, 比如:onMouseEnter,onFocus
+ 如果在函数组件中绑定事件,则调用事件函数不加this
```js
class App extends React.Component {
handleClick(){
console.log('被点击了')
}
render(){
return (
<button onClick={this.handleClick()}></button>
)
}
}
```
##### React事件处理(2事件对象)
+ 可以通过`事件处理程序参数`获取到事件对象
+ React中的事件对象叫做:`合成事件`(对象)
+ 合成事件:兼容所有浏览器,无需担心跨浏览器兼容性问题
```js
function handleClick(e){
e.preventDefault()
console.log('事件对象',e)
}
<a onClick={handleClick}>点击跳转</a>
```
有状态组件和无状态组件
+ 函数组件又叫做`无状态组件`,类组件又叫做`有状态组件`
+ 状态(state)即`数据`
+ 函数组件没有自己的状态,只负责`数据展示`(静态)
+ 类组件有自己的状态,`负责更新UI`(动态)
state的基本使用
+ 状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
+ `state的值是对象`,表示一个组件中可以有多个数据
+ 通过this.state 来获取状态
```js
class Hello extends React.Component {
constructor(){
super()
this.state = {
count:0
}
}
render(){
return (
<div>有状态组件</div>
)
}
}
```
ES6简化语法
```js
class Hello extends React.Component {
state = {
count:0
}
render(){
return (
<div>有状态组件</div>
)
}
}
```
【案例】有状态组件中的state可以定义哪些数据,如何调用
##### 组件中的state和setState()(1setState()修改状态)
+ 状态时可变的
+ 语法:this.setState({要修改的数据})
+ 注意:`不能直接修改state中的值`
+ setState()作用:1、`修改state` 2、`更新UI`
+ 数据驱动视图
```js
class Hello extends React.Component {
state = {
count:0
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={()={
this.setState({
count:this.state.count + 1
})
}}>+1</button>
)
}
}
```
##### 组件中的state和setState()(2从JSX中抽离事件处理程序)
+ JSX中有太多的JS逻辑代码,会使程序混乱
+ 推荐:将逻辑抽离到单独的方法中,保证JSX结构清晰
```js
class Hello extends React.Component {
state = {
count:0
}
onIncrement(){
this.setState({
count:this.state.count + 1
})
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={this.onIncrement()}>+1</button>
)
}
}
```
尝试将事件函数剥离JSX,我们会有:
`TypeError:Cannot read property 'setState' of undefined`
原因:事件处理程序中this的值为undefined
希望:this指向组件实例(render方法中的this即为组件实例)
#### 无状态组件的state
```js
const [count,setCount] = React.useState(0)
const [number,setNumber] = React.useState(1)
```
##### 事件绑定this指向(1箭头函数)
+ 利用箭头函数自身不绑定this的特点
```js
class Hello extends React.Component {
state = {
count:0
}
onIncrement(){
this.setState({
count:this.state.count + 1
})
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={()=>this.onIncrement()}>+1</button>
)
}
}
```
##### 事件绑定this指向(2bind)
+ 利用ES5中的bind() 方法,将事件处理程序中的this与组件实例绑定到一起
```js
class Hello extends React.Component {
state = {
count:0
}
constructor(){
super()
this.onIncrement = this.onIncrement.bind(this)
}
onIncrement(){
this.setState({
count:this.state.count + 1
})
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={()=this.onIncrement()>+1</button>
)
}
}
```
##### 事件绑定this指向(3class的实例方法)
+ 利用箭头函数形式的class实例方法
+ 注意:改语法是实验性的,但babel可以转化该语法
```js
class Hello extends React.Component {
state = {
count:0
}
onIncrement = ()=>{
this.setState({
count:this.state.count + 1
})
}
render(){
return (
<div>计数器:{this.state.count}</div>
<button onClick={this.onIncrement}>+1</button>
)
}
}
```
##### 事件绑定this指向-总结
1、推荐:`使用class的实例方法`
2、箭头函数
3、bind
##### 表单处理(1受控组件概念)
+ HTML中的表单元素是可输入的,也就是有自己的可变状态
+ 而React中可变状态通常保存在state中,并且只能通过setState() 方法来修改
+ React将state与表单元素值value绑定到一起,`由state的值来控制表单元素的值`
+ 受控组件:其值受到React控制的表单元素
##### 表单处理(2受控组件使用步骤)
受控组件设置步骤:
1、在state中添加一个状态,作为表单元素的value值(控制表单元素值的来源)
2、给表单元素绑定change事件,将表单元素的值,设置为state的值(受控表单元素值的变化)
```js
state = {txt:''}
<input type="text" value={this.state.txt} οnchange={e =>
this.setState({txt : e.target.value})} />
```
##### 表单处理(3受控组件的示例)
富文本框textarea
```js
state = {content:''}
handleContent = e=>{
this.setState({
content:e.target.value
})
}
```
```html
<textarea value={this.state.content} onChange={this.handleCOntent}>
</textarea>
```
下拉框select
```js
state = {city:'bj'}
handleCity = e=>{
this.setState({
city:e.target.value
})
}
```
```html
<select value={this.state.city} onChange={this.handleCity}>
<option value="sh">上海</option>
<option value="bj">北京</option>
<option value="gz">广州</option>
</select>
```
复选框
```js
state = {
isChecked:false
}
handleCheck = e => {
this.setState({
isChecked:e.target.value
})
}
```
```html
<input type="checkbox" checked={this.state.isChecked}
onChange={this.handleCheck}/>
```
##### 表单处理(4多表单元素优化)
每个表单元素都有一个单独的事件处理程序处理太繁琐
使用一个事件处理程序同时处理多个表单元素
多表单元素优化步骤
1、给表单元素添加name属性,名称与state相同
```html
<input type="text" \
name="txt"
value={this.state.txt}
onChange={this.handleForm}/>
```
2、根据表单元素类型获取对应值
```js
const value = target.type === 'checkbox' ? target.checked : target.value
this.setState({
[name]:value
})
```
##### 表单处理(5非受控组件)
1、调用React.createRef() 方法创建一个ref对象
```js
constructor(){
super()
this.txtRef = React.createRef()
}
```
2、将创建好的ref对象添加到文本框中
```html
<input type="text" ref={this.txtRef} />
```
3、通过ref对象获取到文本框的值
```js
console.log(this.txtRef.current.value)
```
【案例:取消购物车选中】
【作业:多表单控制】
##### React组件基础总结
1、组件的两种创建方式:函数组件和类组件
2、无状态(函数)组件,负责静态结构展示
3、有状态 (类) 组件,负责更新UI,让页面动起来
4、绑定事件注意this指向问题
5、推荐使用受控组件来处理表单
6、完全利用JS语言的能力创建组件,这是React的思想
## 05-React组件基础综合案例(1案例需求分析)
【案例】评论列表
1)渲染评论列表(列表渲染)
2)没有评论数据时渲染:暂无评论(条件渲染)
3)获取评论信息,包括评论人和评论内容(受控组件)
4)发表评论,更新评论列表(setState() )