欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React?Refs?的使用forwardRef?源碼示例解析

 更新時間:2022年11月07日 09:12:01   作者:冴羽  
這篇文章主要為大家介紹了React?之?Refs?的使用和?forwardRef?的源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

三種使用方式

React 提供了 Refs,幫助我們訪問 DOM 節(jié)點(diǎn)或在 render 方法中創(chuàng)建的 React 元素。

React 提供了三種使用 Ref 的方式:

1. String Refs

class App extends React.Component {
    constructor(props) {
        super(props)
    }
    componentDidMount() {
        setTimeout(() => {
             // 2. 通過 this.refs.xxx 獲取 DOM 節(jié)點(diǎn)
             this.refs.textInput.value = 'new value'
        }, 2000)
    }
    render() {
        // 1. ref 直接傳入一個字符串
        return (
            <div>
              <input ref="textInput" value='value' />
            </div>
        )
    }
}
root.render(<App />);

2. 回調(diào) Refs

class App extends React.Component {
    constructor(props) {
        super(props)
    }
    componentDidMount() {
        setTimeout(() => {
              // 2. 通過實(shí)例屬性獲取 DOM 節(jié)點(diǎn)
              this.textInput.value = 'new value'
        }, 2000)
    }
    render() {
        // 1. ref 傳入一個回調(diào)函數(shù)
        // 該函數(shù)中接受 React 組件實(shí)例或 DOM 元素作為參數(shù)
        // 我們通常會將其存儲到具體的實(shí)例屬性(this.textInput)
        return (
            <div>
              <input ref={(element) => {
                this.textInput = element;
              }} value='value' />
            </div>
        )
    }
}
root.render(<App />);

3. createRef

class App extends React.Component {
    constructor(props) {
        super(props)
        // 1. 使用 createRef 創(chuàng)建 Refs
        // 并將 Refs 分配給實(shí)例屬性 textInputRef,以便在整個組件中引用
        this.textInputRef = React.createRef();
    }
    componentDidMount() {
        setTimeout(() => {
            // 3. 通過 Refs 的 current 屬性進(jìn)行引用
            this.textInputRef.current.value = 'new value'
        }, 2000)
    }
    render() {
        // 2. 通過 ref 屬性附加到 React 元素
        return (
            <div>
              <input ref={this.textInputRef} value='value' />
            </div>
        )
    }
}

這是最被推薦使用的方式。

兩種使用目的

Refs 除了用于獲取具體的 DOM 節(jié)點(diǎn)外,也可以獲取 Class 組件的實(shí)例,當(dāng)獲取到實(shí)例后,可以調(diào)用其中的方法,從而強(qiáng)制執(zhí)行,比如動畫之類的效果。

我們舉一個獲取組件實(shí)例的例子:

class Input extends React.Component {
    constructor(props) {
        super(props)
        this.textInputRef = React.createRef();
    }
    handleFocus() {
        this.textInputRef.current.focus();
    }
    render() {
        return <input ref={this.textInputRef} value='value' />
    }
}
class App extends React.Component {
    constructor(props) {
        super(props)
        this.inputRef = React.createRef();
    }
    componentDidMount() {
        setTimeout(() => {
                this.inputRef.current.handleFocus()
        }, 2000)
    }
    render() {
        return (
            <div>
              <Input ref={this.inputRef} value='value' />
            </div>
        )
    }
}

在這個例子中,我們通過 this.inputRef.current 獲取到 Input 組件的實(shí)例,并調(diào)用了實(shí)例的 handleFocus 方法,在這個方法中,又通過 Refs 獲取到具體的 DOM 元素,執(zhí)行了 focus 原生方法。

Refs 轉(zhuǎn)發(fā)

有的時候,我們開發(fā)一個組件,這個組件需要對組件使用者提供一個 ref 屬性,用于讓組件使用者獲取具體的 DOM 元素,我們就需要進(jìn)行 Refs 轉(zhuǎn)發(fā),這對于 class 組件并不是一個問題,舉個示例代碼:

class Child extends React.Component {
    render() {
        const {inputRef, ...rest} = this.props;
        // 3. 這里將 props 中的 inputRef 賦給 DOM 元素的 ref
        return <input ref={inputRef} {...rest} placeholder="value" />
    }
}
class Parent extends React.Component {
    constructor(props) {
        super(props)
        // 1. 創(chuàng)建 refs
        this.inputRef = React.createRef();
    }
    componentDidMount() {
        setTimeout(() => {
            // 4. 使用 this.inputRef.current 獲取子組件中渲染的 DOM 節(jié)點(diǎn)
            this.inputRef.current.value = 'new value'
        }, 2000)
    }
    render() {
        // 2. 因?yàn)?ref 屬性不能通過 this.props 獲取,所以這里換了一個屬性名
        return <Child inputRef={this.inputRef} />
    }
}

但對于函數(shù)式組件,這卻是一個問題。

我們是不能在函數(shù)組件上使用 ref 屬性的,因?yàn)楹瘮?shù)組件沒有實(shí)例。

所以 React 提供了 forwardRef 這個 API,我們直接看使用示例:

// 3. 子組件通過 forwardRef 獲取 ref,并通過 ref 屬性綁定 React 元素
const Child = forwardRef((props, ref) => (
  <input ref={ref} placeholder="value" />
));
class Parent extends React.Component {
    constructor(props) {
        super(props)
        // 1. 創(chuàng)建 refs
        this.inputRef = React.createRef();
    }
    componentDidMount() {
        setTimeout(() => {
            // 4. 使用 this.inputRef.current 獲取子組件中渲染的 DOM 節(jié)點(diǎn)
            this.inputRef.current.value = 'new value'
        }, 2000)
    }
    render() {
        // 2. 傳給子組件的 ref 屬性
        return <Child ref={this.inputRef} />
    }
}

尤其是在我們編寫高階組件的時候,往往要實(shí)現(xiàn) refs 轉(zhuǎn)發(fā)。我們知道,一個高階組件,會接受一個組件,返回一個包裹后的新組件,從而實(shí)現(xiàn)某種功能的增強(qiáng)。

但也正是如此,我們添加 ref,獲取的會是包裹后的新組件的實(shí)例,而非被包裹的組件實(shí)例,這就可能會導(dǎo)致一些問題。

createRef 源碼

現(xiàn)在我們看下 createRef 的源碼,源碼的位置/packages/react/src/ReactCreateRef.js,代碼其實(shí)很簡單,就只是返回了一個具有 current 屬性的對象:

// 簡化后
export function createRef() {
  const refObject = {
    current: null,
  };
  return refObject;
}

在渲染的過程中,refObject.current 會被賦予具體的值。

forwardRef 源碼

那 forwardRef 源碼呢?源碼的位置/packages/react/src/ReactForwardRef.js,代碼也很簡單:

// 簡化后
const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
export function forwardRef(render) {
  const elementType = {
    $$typeof: REACT_FORWARD_REF_TYPE,
    render,
  };
  return elementType;
}

但是要注意這里的 $$typeof,盡管這里是 REACT_FORWARD_REF_TYPE,但最終創(chuàng)建的 React 元素的 $$typeof 依然為 REACT_ELEMENT_TYPE

關(guān)于 createElement 的源碼分析參考 《React 之 createElement 源碼解讀》,我們這里簡單分析一下,以 InputComponent 為例:

// 使用 forwardRef
const InputComponent = forwardRef(({value}, ref) => (
  <input ref={ref} className="FancyButton" value={value} />
));
// 根據(jù) forwardRef 的源碼,最終返回的對象格式為:
const InputComponent = {
    $$typeof: REACT_FORWARD_REF_TYPE,
    render,
}
// 使用組件
const result = <InputComponent />
// Bable 將其轉(zhuǎn)譯為:
const result = React.createElement(InputComponent, null);
// 最終返回的對象為:
const result = {
  $$typeof: REACT_ELEMENT_TYPE,
  type: {
    $$typeof: REACT_FORWARD_REF_TYPE,
    render,
  }
}

我們嘗試著打印一下最終返回的對象,確實(shí)也是這樣的結(jié)構(gòu):

React 系列

React 之 createElement 源碼解讀

React 之元素與組件的區(qū)別

以上就是React 之 Refs 的使用和 forwardRef 的源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于React Refs使用forwardRef 的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在?React?中使用?Context?API?實(shí)現(xiàn)跨組件通信的方法

    在?React?中使用?Context?API?實(shí)現(xiàn)跨組件通信的方法

    在React中,ContextAPI是一個很有用的特性,可用于組件間的狀態(tài)共享,它允許跨組件傳遞數(shù)據(jù)而無需通過每個組件手動傳遞props,本文給大家介紹在?React?中如何使用?Context?API?來實(shí)現(xiàn)跨組件的通信,感興趣的朋友一起看看吧
    2024-09-09
  • React.js?Gird?布局編寫鍵盤組件

    React.js?Gird?布局編寫鍵盤組件

    這篇文章主要介紹了React.js?Gird?布局編寫鍵盤組件,Grid?布局則是將容器劃分成"行"和"列",產(chǎn)生單元格,然后指定"項(xiàng)目所在"的單元格,可以看作是二維布局
    2022-09-09
  • 深入理解React中何時使用箭頭函數(shù)

    深入理解React中何時使用箭頭函數(shù)

    對于剛學(xué)前端的大家來說,對于React中的事件監(jiān)聽寫法有所疑問很正常,特別是React中箭頭函數(shù)使用這塊,下面這篇文章主要給大家深入的講解了關(guān)于React中何時使用箭頭函數(shù)的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • 淺談React組件props默認(rèn)值的設(shè)置

    淺談React組件props默認(rèn)值的設(shè)置

    本文主要介紹了淺談React組件props默認(rèn)值的設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解React中key的作用

    詳解React中key的作用

    這篇文章主要介紹了React中key的作用,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • React Hooks - useContetx和useReducer的使用實(shí)例詳解

    React Hooks - useContetx和useReducer的使用實(shí)例詳解

    這篇文章主要介紹了React Hooks - useContetx和useReducer的基本使用,本文通過實(shí)例代碼給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-11-11
  • 在React項(xiàng)目中添加吸頂效果的代碼示例

    在React項(xiàng)目中添加吸頂效果的代碼示例

    在大型Web應(yīng)用中,一個常見的設(shè)計(jì)需求是讓某些組件具有吸頂效果,這意味著當(dāng)頁面向下滾動時,該組件會保持在屏幕頂部,在本文中,我們將介紹如何在React項(xiàng)目中實(shí)現(xiàn)吸頂效果。我們將首先討論使用原生JavaScript領(lǐng)域的方法來實(shí)現(xiàn),然后將這些方法與React結(jié)合起來
    2023-06-06
  • 詳解React Fiber的工作原理

    詳解React Fiber的工作原理

    這篇文章主要介紹了React Fiber的工作原理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下
    2021-04-04
  • react如何利用useRef、forwardRef、useImperativeHandle獲取并處理dom

    react如何利用useRef、forwardRef、useImperativeHandle獲取并處理dom

    這篇文章主要介紹了react如何利用useRef、forwardRef、useImperativeHandle獲取并處理dom,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-10-10
  • React實(shí)現(xiàn)歌詞滾動效果(跟隨音樂播放時間滾動)

    React實(shí)現(xiàn)歌詞滾動效果(跟隨音樂播放時間滾動)

    這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)歌詞滾動效果(跟隨音樂播放使勁按滾動),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2024-02-02

最新評論