文章目录
1. setState
1.1 setState 的两种写法
- 对象式
- 函数式
1.2 对象式
// count 初始值为 0
let { count } = this.state
this.setState({
count: count + 1
// 第二个参数为一个可选的回调函数,在数据更新完成之后才会执行
}, () => {
console.log(count) // 1
})
console.log(count) // 0
1.3 函数式
// 对象式其实是函数式的语法糖
this.setState((state, props) => {
return {
count: state.count + 1 // 返回一个新的状态
}
},[callback]) // 和对象式的第二个参数一样
2. lazyLoad(路由懒加载)
import React, { Component, lazy, Suspense } from "react";
import { Route, NavLink } from "react-router-dom";
// 路由懒加载
let About = lazy(() => import("./components/About/About"));
let Home = lazy(() => import("./components/Home/Home"));
export default class App extends Component {
render() {
return (
<div className="App">
<div>
<NavLink to="/demo/about" children="About" />
<NavLink to="/demo/home" children="Home" />
</div>
<div className="content">
// 当组件还没有加载回来时,显示fallback中的组件/DOM元素
<Suspense fallback={<h1>loading...</h1>}>
<Route path="/demo/about" component={About} />
<Route path="/demo/home" component={Home} />
</Suspense>
</div>
</div>
);
}
}
3. hooks
3.1 State Hook
// 可以使用 React.useState、也可以直接导入 useState
import React, { useState } from "react";
export default function App() {
// [数据, 修改数据的方法]
let [count, setCount] = React.useState(0);
let [arr, setArr] = useState([{name: "小红", age: 18}]);
function add() {
// 传入要修改的数据
setCount(count + 1);
}
function addInfo() {
// 要修改的数据,会替换掉原数据
setArr([...arr, {name: "小黄", age: 19}])
}
return (
<div>
<h1>{count}</h1>
<button onClick={add}>点我加1</button>
<button onClick={addInfo}>点我加添加信息</button>
</div>
);
}
3.2 Effect Hook
import { useEffect } from "react"
export default function App() {
let [count, setCount] = React.useState(0);
// 用于模拟类组件中的生命周期钩子
useEffect(() => {
// 组件初始化时的操作、类似于 componentDidMount
return () => {
// 组件销毁时的操作,类似于 componentWillUnmount
}
// 不写 [] 表示任何数据更新都会触发回调,写 [] 可以指定任意数量、数据更新的回调,比如:[count] count 数据更新时触发
},[]) // 用于检测对应数据的更新,类似于 componentDidUpdate
function add() {
setCount(count + 1);
}
return (
<div>
<h1>{count}</h1>
<button onClick={add}>点我加1</button>
</div>
);
}
3.3 Ref Hook
import { useRef } from "react"
// 和 createRef 用法一样
4. Fragment(虚拟DOM)
// Fragment 和 vue 中的 template 很相似
import { Fragment } from "react"
...render(){
// 在页面中不会生成dom,也可以使用 <></> 效果一样,但它并不支持 key 或属性
return <Fragment></Fragment>
}
5. Context(祖孙传值)
// 用于祖孙组件之间的传值
import { createContext, useContext } from "react";
// 创建 context
const MyContext = createContext();
// Provider:传入的数据,Consumer:接收的数据
const { Provider, Consumer } = MyContext;
function App() {
return (
<div>
// 只可以写 value
<Provider value="要传入的数据">
// 后代组件
</Provider>
</div>
)
}
// 后代组件1
function Demo1(){
return (
<div>
<Consumer>
{(value) => {
// value:接收到的数据
}}
</Consumer>
</div>
)
}
// 后代组件2
function Demo2() {
// 接收到的数据
const value = useContext(MyContext)
return <div></div>
}
6. 组件优化
6.1 Component 的2个问题
- 只要执行了 setState(),即使不改变状态数据,组件也会重新 render
- 只要当前组件重新 render,子组件也会重新 render
6.2 解决方案
只有当前组件的 state 或 props 修改时,才会 render
- 设置 shouldComponentUpdate 声明周期方法
shouldComponentUpdate(nextState, nextProps) { // 对比 this.state、nextState 和 this.props、nextProps // 如果改变了就返回 true,如果没有改变就返回 false }
- 使用 PureComponent
import { PureComponent } from "react" class App extends PureComponent { // 这种已经进行了处理,可以直接使用 // 但是使用时需要注意两点问题 // 1. 使用 setState 修改时不要使用同一个地址,地址没变判定为未修改 // 2. 不要直接在组件标签上,通过回调的形式写 render props,会抵消掉 PureComponent 的作用 }
7. Render Props(逆向传值)
// 这种方式可以向上传递数据,类似于 vue 中的作用域插槽
function App() {
return (
<div>
<p> 我是App组件</p>
<Child render={(value) => <span>{`name:${value.name},age:${value.age}`}</span>} />
</div>
);
}
function Child(props) {
return (
<div>
<p> 我是Child组件</p>
{props.render({ name: "小红", age: 18 })}
</div>
);
}
8. 错误边界
// 用于捕获子组件生命周期的错误,只在生产环境会有效果
class App extends Component {
// 子组件生命周期出错就会触发
static getDerivedStateFromError() {
return {
hasError: true
}
}
componentDidCatch() {
console.log("打印错误信息")
}
}
9. 组件通信
- 父子:props、renderProps(逆向传递)
- 兄弟:redux(集中式管理)、发布订阅
- 祖孙:redux(集中式管理)、context、发布订阅