组件类型

  • 函数式无状态组件
  • 类组件
  • 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 )

推荐学习资源


时樾同学
74 声望3 粉丝

前端打杂大户