JSX 语法
<div></div>
使用规则
- 只能返回一个根元素
<>
内容
</>
<React.Fragment>
内容
</React.Fragment>
- 标签必须闭合
- 使用驼峰式命名法给
组件分类
类组件
import React from 'react'
class Comp1 extends React.Component {
render() {
return <div>类组件 Comp1</div>
}
}
export default Comp1
生命周期
含义: 一个组件从被创建到销毁的整个过程叫做生命周期,生命周期其实就是在特定的时候执行的钩子函数。
import React from 'react'
class Comp1 extends React.Component {
// 方法
addCount() {
console.log('addCound');
// console.log(this)
// 类组件修改 state 唯一方式
this.setState({
count: this.state.count + 1
})
}
// 内部状态
state = {
message: '你好, 生命周期',
count: 1
}
// 挂载
constructor(props) {
// 必须先调用supper
super(props)
// 1. 初始化数据(不建议, 太麻烦)
// 2. 绑定this指向
console.log('1. constructor 生命周期执行')
console.log(document.querySelector('.oo'))
}
render() {
console.log('2. render 生命周期执行')
console.log(document.querySelector('.oo'))
return <div className='oo'>
<div>类组件 Comp1----{this.state.message}</div>
<h2>{this.state.count}</h2>
<button onClick={() => this.addCount()}>+1</button>
</div>
}
componentDidMount() {
// 页面第一次渲染完毕执行, 真实dom已经渲染完毕, 可以操作dom
// 发起请求
console.log('3. componentDidMount 生命周期执行')
console.log(document.querySelector('.oo'));
console.log(this)
}
// 更新
shouldComponentUpdate() {
console.log('1. shouldComponentUpdate')
// 一般用来做优化
return false
}
componentDidUpdate() {
// 数据更新完毕
console.log('3. componentDidUpdate ')
}
// 销毁
componentWillUnmount() {
// 1. 取消副作用
}
}
export default Comp1
销毁 componentWillUnmount
一般来说, 在这个生命周期取消副作用, 比如 取消定时器
import React from 'react'
// 定义类组件
class Comp1 extends React.Component {
state = {
timer: null
}
// 三个阶段
// 挂载
constructor(props) {
// 必须调用父类的constructor
super(props);
// 初始化, 函数绑定this
}
render() {
// 就负责渲染
return <div>comp1</div>
}
componentDidMount() {
// 第一次渲染完成执行
// 可以进行副作用操作
this.timer = setInterval(() => {
console.log(new Date())
}, 1000)
}
// 更新
shouldComponentUpdate() {
// state 内部状态
// props 外部状态
return true
}
// render
componentDidUpdate() {
// 更新完毕
}
// 销毁
componentWillUnmount() {
// 取消副作用
clearInterval(this.timer)
}
}
export default Comp1
函数组件
在react@16.8版本之前,函数只可以用来进行UI渲染, 无法进行逻辑交互等复杂业务。 但是在react@16.8之后, 出现了hooks, 可以通过hooks 实现等同于类组件相同的操作。
import React from 'react'
const Comp2 = () => {
return (
<div>
函数组件 Comp2
</div>
)
}
export default Comp2
hooks
useState 声明数据
const [state, setState] = useState(初始值);
setState(新值)
setState((上一次的值) => 新值)
useEffect 副作用函数
- 首页渲染完毕, 执行一次
- 第二个参数不存在, 任何数据发生改变都会执行一次。 存在依赖项, 当依赖参数发生改变,会执行一次
- 返回卸载函数, 当组件被卸载的时候, 该函数执行
useEffect(() => {
// 首次渲染执行
// 更新的时候也会执行, 但是必须依赖的参数发生改变
return () => {
// 组件卸载执行
}
}, [依赖参数])
useNavigate 编程式导航
const navigate = useNavigate();
navigate('/home') // 导航到 /home 路由
navigate(-1) // 返回上一页
// 可选的第二个参数
navigate(路径, {
replace?: boolean;
state?: any;
preventScrollReset?: boolean;
relative?: RelativeRoutingType;
unstable_viewTransition?: boolean;
})
类组件和函数的联系与区别??
- 类组件有生命周期,函数组件没有
- 类组件需要继承 Class,函数组件不需要
- 类组件可以获取实例化的
this,并且基于this做各种操作,函数组件不行 - 类组件内部可以定义并维护
state, 函数组件为无状态组件(可以通过hooks实现)
组件通信
父子通讯: 副组件在调用子组件的时候,传递自定义属性, 传递了三个自定义属性 title, image, desc
<ListItem
title={v.title}
image={v.image}
desc={v.desc}
></ListItem>
子组件通过 this.props 接收到传递过来的自定义属性, 结构赋值
const { title, desc, image } = this.props
子父通信: 副组件传递自定义方法, 由子组件props接收调用即可
// 父组件
<Comp1 count={count} addCount={this.addCount}></Comp1>
// 子组件
<button onClick={this.props.addCount}>+1</button>
context 通信
- 创建context
const MyContext = React.createContext(初始值)
- 提供 Provider
<MyContext.Provider value={共享的值}>
<其他组件></其他组件>
</MyContext.Provider>
- 消费 consumer
// 1. 方式一 类组件
class Index extends React.Components {
static contentType = MyContext
render() {
this.context // 共享的值
return (<DIV></DIV>)
}
}
// 2. 方式一 类组件
class Index extends React.Components {
render() {
this.context // 共享的值
return (<DIV></DIV>)
}
}
Index.contentType = MyContext
// 3. 方式三 类组件|函数组件
class Index extends React.Components {
render() {
return <MyContext.Consumer>
{
(共享的值) => {
}
}
</MyContext.Consumer>
}
}
事件
事件传播
- react 从捕获到目标到冒泡
事件分类
- 合成事件:与原生事件直接在元素上注册的方式不同的是,React的合成事件不会直接绑定到目标DOM节点上,用事件委托机制,以队列的方式,从触发事件的组件向父组件回溯,直到Root节点。因此,React组件上声明的事件最终绑定到了Root对象(React17之前是Document)上。在Root节点,用一个统一的监听器去监听,这个监听器上保存着目标节点与事件对象的映射。当组件挂载或卸载时,只需在这个统一的事件监听器上插入或删除对应对象;当事件发生时(即Root上的事件处理函数被执行),在映射里按照冒泡或捕获的路径去组件中收集真正的事件处理函数,然后,由这个统一的事件监听器对所收集的事件逐一执行。
合成事件与原生事件区别
- 事件名称必须小驼峰
- 事件驱动函数要写成引用形式 { 函数 } 或者 { () => 函数() }
- 阻止行为不同