1、项目搭建与结构
2、类组件和函数组件
主要区别:
1、函数组件没有生命周期
2、函数组件没有this指向
3、函数组件没有状态
4、函数组件通过hooks实现各种操作
5、props在函数的第一个参数接收
6、函数体相当于类组件的render函数
import React from 'react'
function App ( ) {
function Fn ( ) {
return < div> fn hello< / div>
}
class ClassHello extends React. Component {
constructor ( props ) {
super ( props)
}
render ( ) {
return < div> class hello < / div>
}
}
return (
< div className= "App" >
< Fn> < / Fn>
< ClassHello> < / ClassHello>
< / div>
) ;
}
export default App;
3、js与jsx语法
1、jsx和react是相互独立的
2、写法相似,更加简便
3、可以和js混用
4、最终会转化为和一个【React-element对象】
5、不借助jsx,可以通过React.createElement创建
3.1 创建DOM的两种方式
二者最终得到的内容是一致的,均是React的element对象
import React from 'react'
function App ( ) {
function Fn ( ) {
return React. createElement ( 'div' , [ ] , 'hello,fn' )
}
class ClassHe extends React. Component {
constructor ( props ) {
super ( props)
}
render ( ) {
return < div> hello, class < / div>
}
}
return (
< div className= "App" >
< Fn> < / Fn>
< ClassHe> < / ClassHe>
< / div>
) ;
}
export default App;
3.2 jsx中不同类型数据的渲染.js
1、字符串/数字 => 直接渲染
2、对象(vue中当成字符串渲染)
element对象 => 直接渲染
普通对象 => 取到每一项后可以渲染
3、数组(普通/元素数组) => 把数组中的每一项进行渲染
4、表达式 => 得到运行结果渲染
5、方法 => 无法渲染
6、布尔值 => 不渲染
7、undefined/null => 不渲染
import React from 'react'
function App ( ) {
const str = 'good !!!'
const num = 123
const obj = {
a : 1
}
const eleObj = < span> span< / span>
const arr = [ 1 , 2 , 3 ]
const eleArr = [
< p> 1111 < / p> ,
< p> 2222 < / p> ,
< p> 3333 < / p>
]
const boll = false
var ss
const na = null
return (
< div className= "App" >
< span> 字符串:< / span>
{ str} < br / >
< span> 数字:< / span>
{ num} < br / >
< span> 普通对象:< / span>
{ }
{ obj. a} < br / >
< span> 元素对象:< / span>
{ eleObj} < br / >
< span> 普通数组:< / span>
{ arr} < br / >
< span> 元素数组:< / span>
{ eleArr}
< span> 表达式:< / span>
{ arr. length === 3 ? obj. a : '' } < br / >
< span> 布尔值:< / span>
{ boll} < br / >
< span> undefined : < / span>
{ ss} < br / >
< span> null :< / span>
{ na} < br / >
< / div>
) ;
}
export default App;
4、事件绑定
1、写法类似原生 on + 方法名(首字母大写)
2、给事件赋值为某个方法,但是不要执行
4.1 方法写在外面
import React from 'react'
class App extends React. Component {
handleClick = ( ) => {
console. log ( '点击了按钮' ) ;
}
render ( ) {
return (
< button onClick= { this . handleClick} > 点我触发事件< / button>
)
}
}
export default App;
4.2 方法写在里面
import React from 'react'
class App extends React. Component {
render ( ) {
return (
< button onClick= { ( ) => {
console. log ( '点击了按钮' ) ;
} } > 点我触发事件< / button>
)
}
}
export default App;
4.3 注意事项
【特别注意】
1、类组件想要拿到事件处理函数中this要处理 不然会undefined
(1) 事件处理函数声明时,声明为【箭头函数+赋值语句】
(2) 使用bind改变this指向,在需要传参时多用
(3) 内联式写法,函数写为【匿名函数+箭头函数】
2、给事件绑定的是一个方法,且不要直接调用
事件处理函数声明时,声明为【箭头函数+赋值语句】
import React from 'react'
class App extends React. Component {
handleClick = ( ) => {
console. log ( this ) ;
}
render ( ) {
return (
< button onClick= { this . handleClick ( ) } > 点我触发事件< / button>
)
}
}
export default App;
使用bind改变this指向,在需要传参时多用
import React from 'react'
class App extends React. Component {
handleClick ( a ) {
console. log ( this , a) ;
}
render ( ) {
return (
< button onClick= { this . handleClick . bind ( this , '传参' ) } > 点我触发事件< / button>
)
}
}
export default App;
内联式写法,函数写为【匿名函数+箭头函数】
import React from 'react'
class App extends React. Component {
render ( ) {
return (
< button onClick= { ( ) => {
console. log ( this ) ;
} } > 点我触发事件< / button>
)
}
}
export default App;
4.4 事件绑定其他操作
1、传递参数 :bind(this,'参数')
2、获取事件对象 e
3、阻止默认行为、冒泡等
import React from 'react'
class App extends React. Component {
handleClick = ( a, b, e ) => {
console. log ( '接收参数' , a, b) ;
console. log ( '合成事件对象' , e) ;
console. log ( '原生事件对象' , e. nativeEvent) ;
e. stopPropagation ( ) ;
e. preventDefault ( ) ;
}
render ( ) {
return (
< button onClick= { this . handleClick . bind ( this , 1 , 2 ) } > 点我触发事件< / button>
)
}
}
export default App;
5、响应式数据(类组件)
1、react不能像vue一样【直接修改】触发更新
2、react直接修改能修改值,无法触发更新
3、react没有像vue的get和set监听,借助【setState】触发更新
5.1 setState的本质
1、修改数据
2、触发更新
以下两种写法是等价的
add = ( ) => {
this . setState ( {
a : ++ this . state. a
} )
}
add = ( ) => {
this . state. a += 1
this . setState ( { } )
}
5.2 setState 获取最新值
1、setState 修改值是异步操作
2、获取最新值要在setStete第二个参数【回调函数】中获取
this . setState ( {
a : ++ this . state. a
} , ( ) => {
console. log ( '拿到a最新的值' , this . state. a) ;
} )
5.3 setState 细节
1、setState传递对象,通过浅合并(Object.assign),并非替换
2、由于浅合并,深层次的修改需要先赋值一份
import React from 'react'
class App extends React. Component {
state = {
a : 0 ,
b : 1 ,
c : {
c1 : 2 ,
c2 : 3
}
}
add = ( ) => {
this . setState ( {
a : ++ this . state. a,
c : {
... this . state. c,
c2 : 4
}
} , ( ) => {
console. log ( '拿到a最新的值' , this . state. a) ;
} )
}
render ( ) {
return < div>
< span> 获取状态:< / span>
{ this . state. a} < br / >
< span> c2的值:< / span>
{ this . state. c. c2} < br / >
< span> 修改状态:< / span>
< button onClick= { this . add} > 点我修改< / button> < br / >
< / div>
}
}
export default App;
5.4 setState的一些特性
1、多次修改数据,会合并为一次,最后触发更新
2、setState每次调用都会触发更新(无论数据是否修改)
借助 PureComponent 优化类组件
a、数据不变,组件不刷新
b、当修改对象和数组时,要先解除引用,否则不更新
3、不要再render中调用setState
addArr1 = ( ) => {
this . state. arr. push ( 4 )
this . setState ( {
arr : this . state. arr
} , ( ) => {
console. log ( this . state. arr) ;
} )
}
addArr = ( ) => {
let arr_ = [ ... this . state. arr]
arr_. push ( 4 )
this . setState ( {
arr : arr_
} , ( ) => {
console. log ( this . state. arr) ;
} )
}
6、条件渲染
1、利用js编写自定义逻辑
2、根据逻辑(true/false)渲染相应的内容
3、主要方式
(1) 三元表达式
(2) && ||
(3) if else
import React from 'react'
class App extends React. PureComponent {
state = {
show : true ,
isHot : true
}
fn = ( ) => {
if ( this . state. show) {
return < span> if < / span>
} else {
return < span> else < / span>
}
}
handleClick = ( ) => {
this . setState ( {
show : ! this . state. show,
isHot : ! this . state. isHot
} )
}
render ( ) {
return < div>
< h3> 条件渲染< / h3>
{ }
{ this . state. show ? '显示' : '隐藏' } < br / >
{ }
{ this . state. isHot && '天气很热' } < br / >
{ }
{ this . fn ( ) } < br / >
< button onClick= { this . handleClick} > 点我切换< / button>
< / div>
}
}
export default App;
7、列表渲染
1、使用数组遍历方法 将后端返回的数组中每一项取出来渲染成jsx
(1) 拿到原始数据:后端数据
(2) 将每一项数据转化为DOM元素
(3) jsx 渲染
2、常用方法
(1) map 有返回值
(2) forEach 没有返回值
(3) filter 过滤
import React from 'react'
class App extends React. PureComponent {
state = {
arr : [ 1 , 2 , 3 ] ,
eleArr : [
< div> 1 < / div> ,
< div> 2 < / div> ,
< div> 3 < / div> ,
]
}
getArr = ( ) => {
let newArr = [ ]
this . state. arr. forEach ( item => {
newArr. push ( < p key= { item} > { item} < / p> )
} )
return newArr
}
render ( ) {
return < div>
< h3> 列表渲染< / h3>
{ this . state. arr} < br / >
{ this . state. eleArr}
< hr / >
{ }
{
this . state. arr. map ( item => (
< h3 key= { item} > { item } < / h3>
) )
}
< hr / >
{ }
{ this . getArr ( ) }
< / div>
}
}
export default App;
8、样式操作
1、class类名设置
(1) 必须写成 className
(2) 样式单独写在一个css文件中
如果不做处理,样式会全局生效(产生样式污染)
(3) 只能接受一个字符串 '' {}
2、style内联写法
不能像原生一样写成字符串'',必须写成对象 {{ }}
3、解决样式污染
(1) 改名 将 .css => .module.css
(2) 将样式文件引入为对象 import sonStyle from ''
(3)【sonStyle.son】/【sonStyle['son']】取出类名使用
4、动态控制类名
引入状态,根据状态使用条件渲染出切换类名(拼接字符串)
(1) 手动拼接字符串(少量)
(2) 借助 classnames 拼接
a、帮助我们生成计算好的类名的字符串
8.1 手动拼接字符串
import React from 'react'
import './App.css'
class App extends React. PureComponent {
state = {
isShow : true
}
handle = ( ) => {
this . setState ( {
isShow : ! this . state. isShow
} )
}
render ( ) {
return (
< div className= "App" >
{ }
< span className= { this . state. isShow ? 'color' : '' } > 动态添加类名< / span> < br / >
< button onClick= { this . handle} > 点我切换< / button>
< / div>
)
}
}
export default App;
8.2 借助 classnames 拼接
import React from 'react'
import classnames from 'classnames'
import style from './App.module.css'
class App extends React. PureComponent {
state = {
isShow : true
}
handle = ( ) => {
this . setState ( {
isShow : ! this . state. isShow
} )
}
render ( ) {
return (
< div className= { style. App} >
{ }
< span className= { classnames ( {
{ }
[ style[ 'color' ] ] : this . state. isShow
} ) } > 动态添加类名< / span> < br / >
< button onClick= { this . handle} > 点我切换< / button>
< / div>
)
}
}
export default App;
9、受控组件和非受控组件
回想原生:
1、获取表单的值 onInput={this.handleClick}
a、绑定监听事件 input/change
b、通过【e.target.value】获取
2、设置表单的值 value={this.state.inputValue}
设置value/checke属性
import React from 'react'
class App extends React. PureComponent {
state = {
inputValue : ''
}
handleClick = ( e ) => {
this . setState ( {
inputValue : e. target. value
} )
}
change = ( ) => {
this . setState ( {
inputValue : 11
} )
}
render ( ) {
return (
< div>
< input value= { this . state. inputValue} onInput= { this . handleClick} / >
< span> { this . state. inputValue} < / span> < br / >
< button onClick= { this . change} > 变更inputValue< / button>
< / div>
)
}
}
export default App;
9.1 受控组件(双向的)
1、表单的值可以获取【state】,并可以由开发者靠代码【setState】去更改
2、可以通过设置state中的值改变表单中的值
3、将表单数据添加到state中,可以通过【state/setState】对数据进行获取和修改
9.2 受控组件(无状态的)
1、表单的值我们只能获取【通过给输入框打标识获取】
2、我们仅做了事件监听,没有设置 value/checked 属性
3、没有设置 state
9.3 关于复选框
1、 value 选中后的值
2、checked 控制是否选中