组件类型
- 函数式无状态组件
- 类组件
- hooks组件
- 高阶组件
代码演示
// 函数式无状态组件
function App (props){
return <div>hello world</div>
}
// 类组件
class App extends React.Component {
render(
return <div>hello world</div>
)
}
// hook组件
function customHook(){
let [dog,setDog] = useState('工具狗')
return <div onClick={() => setDog('大家好,我是工具狗')}>{dog}</div>
}
//高阶组件
function Hello (props){
return <div>{props.name}-{props.age}</div>
}
const Hoc = Comp => {
let name = '招待所管理员'
return props => <Comp {...props} name={name}></Comp>
}
let WithHello = Hoc(Hello)
class A extends React.Component {
render(){
return <div><WithHello age='19'></WithHello></div>
}
}
懒加载组件
- React.lazy()(React.lazy(()=>import('./lazy')))
- React.Suspense
提示:常结合路由使用
代码演示
let Lazy = React.lazy(()=>import('./lazy'))
function App(){
return (
<div className="App">
<React.Suspense fallback='别急,小姐姐在来的路上'>
<Lazy></Lazy>
</React.Suspense>
</div>
)
}
错误边界
- static getDerivedStateFromError 、 componentDidCatch
- 只能捕获子组件的错误,不能捕获自身的错误
- 事件处理异常也捕获不了
- 异步代码异常也捕获不了(例如:setTimeout)
- 服务端渲染异常也捕获不了
- 简单来说只能捕获ui错误
- 在生产模式下生效
代码演示
import React from 'react'
// 定义错误边界错误组件,ErrorBoundary.js
class ErrorBoundary extends React.Component {
constructor(props){
super(props)
this.state = {
isError:false
}
}
static getDerivedStateFromError(error){
return {
isError: true
}
}
componentDidCatch(error){
console.log(error,'过来看看你的错误');
}
render(){
return (
<div>
{
this.state.isError ? <h2>哦和,页面出现异常了,可以摸鱼了</h2> : this.props.children
}
</div>
)
}
}
export default ErrorBoundary
// 使用,App.js
function App(){
return (
<div>
<ErrorBoundary>
...这里有一大堆xxx组件
</ErrorBoundary>
</div>
)
}
跨组件通信
- Context
定义方式(父组件)
- React.createContext()
let MyContext = React.createContext()
class App extends React.Component {
render(){
return (
<div className="App">
<MyContext.Provider value='别急,她来了'>
<Test></Test>
</MyContext.Provider>
</div>
)
}
}
export default App;
使用方式(子组件)
- static contextType
- Consumer
- useContext
class Test extends React.Component {
// 第一种方式
static contextType = MyContext
render(){
return <div>{this.context}</div>
}
// 第二种方式
render(){
return (
<MyContext.Consumer>
{
value => value
}
</MyContext.Consumer>
)
}
}
// 第三种只能用在 hook 函数组件
function Test (){
let value = useContext(MyContext)
return <div>{value}</div>
}
注意:Context需要同一上下文(不知上下文可以问一下高中老师,我高中老师是xxx野衣,所以我上下文学得挺好的)
Ref转发
- React.forwardRef (多于用在高阶组件)
代码演示
let Test = React.forwardRef((props,ref)=>{
return (
<button ref={ref}>按钮</button>
)
})
class App extends React.Component {
render(){
return (
<div className="App" onClick={()=>{console.log(this.test)}}>
<Test ref={test=>this.test=test}></Test>
</div>
)
}
}
将一个组件挂载到任意位置
- ReactDOM.createPortal(vue3中的teleport)
代码演示
function Test(){
return (
ReactDom.createPortal( <button>工具狗</button>,document.querySelector('body'))
)
}
分析一个组件挂载或者更新的消耗
- React.Profiler
代码演示
function Test(){
return <button>工具狗</button>
}
class App extends React.Component {
handle = (id)=>{
console.log(id)
}
render(){
return (
<div className="App">
<React.Profiler id='test' onRender={this.handle}>
<Test></Test>
</React.Profiler>
</div>
)
}
}
React.Profiler的onRender回调参数及其解释
- id (发生提交的 Profiler 树的 “id”)
- phase ("mount" (如果组件树刚加载) 或者 "update" (如果它重渲染了)之一 )
- actualDuration ( 本次更新 committed 花费的渲染时间 )
- baseDuration ( 估计不使用 memoization 的情况下渲染整颗子树需要的时间 )
- startTime ( 本次更新中 React 开始渲染的时间 )
- commitTime ( 本次更新中 React committed 的时间 )
- interactions ( 属于本次更新的 interactions 的集合 )
检验props的类型
- propTypes ( static propTypes / class.propTypes )
代码演示
class Dog extends React.Component{
static propTypes = {}
}
// 或者
Dog.propTypes = {}
注意:propTypes已经被分出去,要自行npm
组件更新浅比较(避免不必要的更新)
- React.PureComponent
- React.memo (仅检测props)
代码演示
//React.PureComponent
class App extends React.PureComponent{}
const Test = React.memo(function(){
return <button>工具狗</button>
})
// React.memo , 可通过第二个参数重新它的比较规则
class App extends React.PureComponent {
render(){
return (
<div className="App">
<Test></Test>
</div>
)
}
}
验证对象是否为React元素
- React.isValidElement ( 返回值为false或者true )
代码演示
class App extends React.PureComponent {
render(){
return (
<div className="App">
{
React.isValidElement(<Test/>) ? <Test></Test> : ''
}
</div>
)
}
}
定义ref方式
- 直接字符串(ref='xxx')
- 使用一个回调函数 (ref=>this.xxx=ref)
- 使用React提供的顶层Api ( React.createRef )
- Hooks提供的Api ( useRef )
推荐学习资源
- 官网,虽然经常给吐槽
- 体德美全面发展学习网站
- 深入React技术栈(书籍,有PDF,需要的留言)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。