前端知识点react

React 高级API用法 Context&Refs转发

2022-07-03  本文已影响0人  咕叽咕叽先生

1、Context

前言

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

使用场景

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>
  }
}

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>);
    }
}

上一篇 下一篇

猜你喜欢

热点阅读