1.基础的React
1.1 Context与ContextType
Context提供了一种方式,能够让数据在组件树中传递而不必一级一级的手动传递,但会让组件失去独立性。
context结构
API:createContext(defaultValue?)
import {createContext} from 'react'
const BatteryContext = createContext()
<BatteryContext.Provider value={}>
</BatteryContext.Provider>
<BatteryContext.Consumer>
{
battery=><h1>{battert}</h1>
}
</BatteryContext.Consumer>
static contextType = BatteryContext
render(){
const battery = this.context
}
1.2 lazy与Suspense
暂时没有资源展示---->延迟加载:
- Webpack - Code Splitting
把一个页面人为的划分为模块进行导入 - import
1.做静态模块导入
import 。。。 from
2.动态模块导入
import('').then(...)
typeof import
webpack就会做一次代码拆分,把import的依赖打包成一个独立的文件,默认情况下,不会马上加载它,只有用到的时候才会导入。指组件渲染的时候。封装的是组件导入的行为,而不是组件本身。而且导入意味着网络请求。
const About = lazy=(()=>import(/*webpackChunkName:'about'*/'./about.jsx'))
lazy的返回就是一个组件
用了lazy后,会存在一个加载中的空档,不知道什么时候加载
这时候用Suspense
<Suspense fallback=(<div>About</div>)>
<About>
</About>
</Suspense>
block request url阻止获取请求(当出现加载错误的时候,suspense不能捕获,但错误边界可以)
//ErrorBoundary错误边界
componentDidCatch(){
this.setState({
hasError:true
})
}
//一旦发生错误,就返回一个新的state数据,并合并到新的state之中
static getDerivedStateFromError(){
return {
hasError:true
}
}
页面首次加载时的性能问题
1.3 memo
shouldComponentUpdate(nextProps,nextState){
if(nextProps.name === this.props.name){
//下一次属性中的name和当前属性中的name,如果相等就不再重新渲染,不想等就重新渲染
return false
}else{
return true
}
}
//或者用PureCompent,需要导入{PureCompent } from React,只有传入数据的本身对比
//(第一级发生变化,比如对象内部不算)2.传入回调函数每次都会重新渲染),内部的数据变化就不行
class Foo extends PureCompent{
}
memo
//函数式的不能用Pure,但是有memo
import {memo} from 'react'
const Foo = memo(function Foo(props){//返回一个组件
return ()
})
2.React Hooks
类组件的问题:
- 状态难以复用(渲染组件,高阶组件)
- 渲染属性和高阶组件导致层级冗余
- 生命周期函数混杂不相干逻辑
- 相干逻辑分散在不同的生命周期
- this指向复杂
hooks优势: - 函数组件无this问题
- 自定义hooks方便复用状态逻辑
- 副作用关注点分离
2.1 useState
import {useState} from 'react'
const [count ,setCount] = useState(0)
onClick={()=>{setCount(count +1)}}
use每次渲染按照稳定的顺序和稳定的次数。
2.2 useEffect
副作用:
- 绑定事件
- 网络请求
- 访问DOM
副作用的时期:
- Mount之后
- Update之前
- Unmount之前
useEffect
useEffect(()=>{
window.addEventListener('resize',onResize)
console.log('count')
return () => {
//清空状态函数
window.removeEventListener('resize',onResize)
}
},[])
传入空数组说明只执一次。
2.3 useContext与useMemo/useCallback
import {createContext,useContext} from 'react'
const CountContext = createContext()
<CountContext.Provider value={}></>
function Counter(){
const count = useContext(CountContext)
console.log(count)
}
useMemo:
仅仅用来做性能优化使用,不能做改变渲染逻辑的用途
const double = useMemo(()=>{
return count *3
},[count])调用时机在渲染期间,而useEffect是在副作用时期,useMemo是有返回值,可以参与渲染,不能循环依赖
useCallback:
const onClick = useMemo(()=>{
return ()=>{
console.log('click')
}
},[])
const onClick = useCallback(()=>{
console.log('click')
},[])
useMemo返回值是一个函数。则等价于useCallback
使onclick函数不会变化,useCallback会创建函数,但是如果没有变化,则不会返回,当依赖变化时,才会执行。
2.4 useRef
- 获取子组件或者DOM节点的句柄
- 渲染周期之间共享数据的存储
state也能储存数据,但state会触发重渲染。
import {useRef} from "react"
const counterRef = useRef()
<Counter ref= {counterRef}>
console.log(counterRef.current)
//注意只能是类组件
const it = useRef()
it.current = ....
下一次渲染就能获取到了
2.5 Redux
redux:状态容器与数据流管理
- 单一数据源
- 状态不可变(修改完之后不再是以前的Redux)
- 用纯函数来修改状态