美文网首页前端知识点react
React 高级API用法 Context&Refs转发

React 高级API用法 Context&Refs转发

作者: 咕叽咕叽先生 | 来源:发表于2022-07-03 10:08 被阅读0次

1、Context

前言

react 中组件数据传递是通过props属性 单向传递的,但当组件层级过多时组件数据传递会变繁琐。Context允许数据隔代传递,而不必显式的通过组件树逐层传递props。从而使局部数据“共享”。

使用场景

  • 父组件用Provider生产数据,子组件使用Consumer消费数据
  • 父组件用Provider生产数据,组件使用ContextType接收数据(只用于类组件)
  • 动态和静态Context(父组件更新Context,被Provider包裹的子组件刷新数据,没被Provider包裹的子组件使用Context默认值)
  • 在嵌套组件中更新Context(子组件通过Context传递的函数更新数据)
  • 消费多个Context (createContext多个Context对象父组件通过Provider 层层嵌套子组件,子组件通过Consumer 层层嵌套取数据)

ProductContext.js:创建的Context组件文件
ProviderPage.js:父组件(数据生产者)
MiddlePage.js:中间组件
ConsumerPage.js:子组件(数据消费者)
GrandSonPage.js:子组件(数据消费者)

场景1:父组件用Provider生产数据,子组件使用Consumer消费数据

src\page\context\part_1\ProviderPage.js

场景2:父组件用Provider生产数据,组件使用ContextType接收数据(只用于类组件 因为需要使用static)

作用:contextType 可以简化 context 的使用,不使用 consumer 也可以共享变量
src\page\context\part_2\ProviderPage.js

场景3:动态和静态Context(父组件更新Context,被Provider包裹的子组件刷新数据,没被Provider包裹的子组件使用Context默认值)

作用:contextType 可以简化 context 的使用,不使用 consumer 也可以共享变量
src\page\context\part_3\ProviderPage.js

场景4:在嵌套组件中更新Context(子组件通过Context传递的函数更新数据)

子组件通过调用父组件context中的函数 通知父组件更新状态 从而达到子传父组的效果
src\page\context\part_4\ProviderPage.js

场景5:消费多个Context (createContext多个Context对象父组件通过Provider 层层嵌套子组件,子组件通过Consumer 层层嵌套取数据)

父组件中通过多层嵌套 将context 传入子组件 使数据更有层次

2、Refs转发

什么是refs

Refs 是一个 获取 DOM节点或 React元素实例的工具。在 React 中 Refs 提供了一种方式,允许用户访问DOM 节点或者在render方法中创建的React元素。

创建 Refs

1、React.createRef() 【React >=16.3】

这种方式既可以在函数组件中使用,也可以在class组件中使用。

class App extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
    componentDidMount() {
        console.log(this.myRef)
        console.log(this.myRef.current)
    }
  render() {
    return <div ref={this.myRef}>React.createRef()</div>
  }
} 
2、React.useRef() 【React >=16.8】

这种只可以在函数组件中使用。

const App = ()=>{
    const myRef = React.useRef(null)
    //const myRef = React.createRef() 两种创建 ref 对象的方式都可以
    React.useEffect(()=>{
        console.log(myRef)
        console.log(myRef.current)
    },[]) //模拟生命周期
    return (
        <div ref={myRef}>React.useRef()</div>
    )
}
3、回调 Refs
const App = () => {
  // 初始化定义ref
  let myRef = null;
  // 初始化定义ref
  React.useEffect(() => {
      console.log(myRef)
      console.log(myRef.current)
  }, []) //模拟生命周期
  return (
      <div ref={(ref) => myRef = ref} >回调 Refs</div>
  )
}


class App extends React.Component {
  constructor(props) {
      super(props);
  }
  componentDidMount() {
      console.log(this.myRef)
      console.log(this.myRef.current)
  }
  render() {
      return <div ref={ref => this.myRef = ref}>React.createRef()</div>
  }
}
  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底DOM 元素作为其 current 属性。
  • 当 ref 属性用于 class 组件时,ref 对象的current属性为组件实例对象 。
  • 函数组件无法使用 ref 属性,因为他们没有实例。

Refs转发应用场景

解决获取子组件通内部的 DOM 元素/方法.

const FancyButton = React.forwardRef((props, ref) => {
    let myRef
    useImperativeHandle(ref, () => {
        return {
            func
        };
    })
    function func() {
        console.log('执行我', myRef);
    }
    return <button ref={ref => myRef = ref} className='FancyButton' > {props.children}</button >
})

function App() {
    let myHandle
    React.useEffect(() => {
        // useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。
        console.log(myHandle)
        console.log(myHandle.func())
    }, []) //模拟生命周期
    return (
        <FancyButton ref={handle => myHandle = handle} >Click me</FancyButton>
    )
}

使用props自定义onRef/onRefDom属性 用于获取子组件方法或属性

缺点:如果一个组件被多次使用,正常情况下想要调用其组件内的方法需要传入props来调用,每次传入的话就比较多余。


class Child extends React.Component {
    constructor(props) {
        super(props);
        this.props.onRef && this.props.onRef(this);
    }
    func() {
        console.log("执行我")
    }
    render() {
        return (<div ref={node => this.props.onRefDom(node)}>子组件</div>);
    }
}

class App extends React.Component {
    handleOnClick = () => {

    }
    componentDidMount() {
        console.log(this.Child)
        console.log(this.ChildDom)
        this.Child.func();
    }
    render() {
        return (<div>
            <button onClick={this.handleOnClick}>click</button>
            <Child onRef={node => this.Child = node} onRefDom={node => this.ChildDom = node}></Child>
        </div>);
    }
}

相关文章

  • React高阶组件之rc-notification源码解析

    github地址 demo地址 React Notification UI 组件 安装 用法 API Notifi...

  • React.createContext

    Context被翻译为上下文,在React的官方文档中归类于高级部分,属于React的高级API,但官方并不建议在...

  • 从高阶函数到高阶组件

    介绍 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的...

  • 高阶组件简介

    一、定义 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API...

  • Paint滤镜-ColorFilter、混合模式-Xfermod

    本篇文章主要讲Paint的高级用法,想看Paint基础API的同学,请点击这里:Paint基础API 1、pain...

  • React - 高阶组件

    高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分...

  • React API

    React 中文 API https://react.docschina.org/docs/react-api.html

  • 高阶组件

    一、高阶组件(HOC)是React 中用于复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分,它...

  • 一文学会React Hooks

    前言 本文全面介绍了React Hooks的所有API概念、用法、丰富的demo以及部分底层原理。 实际上,Rea...

  • Kafka消费过程分析

    kafka提供了两套consumer API:高级Consumer API和低级API。 高级API 1)高级AP...

网友评论

    本文标题:React 高级API用法 Context&Refs转发

    本文链接:https://www.haomeiwen.com/subject/kbhcbrtx.html