第329天:React的refs的理解

2021-02-19 山科小站
React的refs的理解

Refs提供了一種方式,允許我們訪問DOM節點或在render方法中創建的React元素。

描述

在典型的React數據流中,props是父組件與子組件交互的唯一方式,要修改一個子組件,你需要使用新的props來重新渲染它,但是在某些情況下,你需要在典型數據流之外強制修改子組件,被修改的子組件可能是一個React組件的實例,也可能是一個DOM元素,對於這兩種情況React都提供了解決辦法。
避免使用refs來做任何可以通過聲明式實現來完成的事情,通常在可以使用props與state的情況下勿依賴refs,下面是幾個適合使用refs的情況:

管理焦點、文本選擇或媒體播放。

觸發強制動畫。

集成第三方DOM庫。

使用

React提供的這個ref屬性,表示為對組件真正實例的引用,其實就是ReactDOM.render()返回的組件實例,需要區分一下渲染組件與渲染原生DOM元素,渲染組件時返回的是組件實例,而渲染DOM元素時,返回是具體的DOM節點,React的ref有3種用法。

字符串

ref可以直接設置為字符串值,這種方式基本不推薦使用,或者在未來的React版本中不會再支持該方式。這主要是因為使用字符串導致的一些問題,例如當ref定義為string時,需要React追蹤當前正在渲染的組件,在reconciliation階段,React Element創建和更新的過程中,ref會被封裝為一個閉包函數,等待commit階段被執行,這會對React的性能產生一些影響等。

class InputOne extends React.Component {
componentDidMount() {
this.refs.inputRef.value = 1;
}
render() {
return <input ref="inputRef" />;
}
}

回調

React支持給任意組件添加特殊屬性,ref屬性接受一個回調函數,其在組件被加載或卸載時會立即執行。

當給HTML元素添加ref屬性時,ref回調接收了底層的DOM元素作為參數。

當給組件添加ref屬性時,ref回調接收當前組件實例作為參數。

當組件卸載的時候,會傳入null。

ref回調會在componentDidMount或componentDidUpdate等生命周期回調之前執行。

Callback Ref我們通常會使用內聯函數的形式,那麼每次渲染都會重新創建,由於React會清理舊的ref然後設置新的,因此更新期間會調用兩次,第一次為null,如果在Callback中帶有業務邏輯的話,可能會出錯,可以通過將Callback定義成類成員函數並進行綁定的方式避免。

class InputTwo extends React.Component {
componentDidMount() {
this.inputRef.value = 2;
}
render() {
return <input ref={(element) =>this.inputRef = element} />;
}
}

API創建

在React v16.3中經0017-new-create-ref提案引入了新的React.createRef的API,當ref被傳遞給render中的元素時,對該節點的引用可以在ref的current屬性中被訪問,ref的值根據節點的類型而有所不同:

當ref屬性用於HTML元素時,構造函數中使用React.createRef()創建的ref接收底層DOM元素作為其current屬性。

當ref屬性用於自定義class組件時,ref對象接收組件的掛載實例作為其current屬性。

不能在函數組件上使用ref屬性,因為他們沒有實例。

對比新的CreateRef與Callback Ref,並沒有壓倒性的優勢,只是希望成為一個便捷的特性,在性能上會會有微小的優勢,Callback Ref採用了組件Render過程中在閉包函數中分配ref的模式,而CreateRef則採用了Object Ref。

class InputThree extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.value = 3;
}
render() {
return <input ref={this.inputRef} />;
}
}

示例
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>React</title>
</head>

<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
class InputOne extends React.Component {
componentDidMount() {
this.refs.inputRef.value = 1;
}
render() {
return <input ref="inputRef" />;
}
}

class InputTwo extends React.Component {
componentDidMount() {
this.inputRef.value = 2;
}
render() {
return <input ref={(element) =>this.inputRef = element} />;
}
}

class InputThree extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.value = 3;
}
render() {
return <input ref={this.inputRef} />;
}
}


var vm = ReactDOM.render(
<>
<InputOne />
<InputTwo />
<InputThree />
</>,
document.getElementById("root")
);
</script>

</html>

每日一題
https://github.com/WindrunnerMax/EveryDay

參考
https://zhuanlan.zhihu.com/p/40462264
https://www.jianshu.com/p/4e2357ea1ba1
https://juejin.cn/post/6844903809274085389
https://juejin.cn/post/6844904048882106375
https://segmentfault.com/a/1190000008665915
https://zh-hans.reactjs.org/docs/refs-and-the-dom.html

React的refs的理解React的refs的理解

相關焦點

  • 在 React 組件中使用 Refs 指南
    這時候就需要 refs 出場了。我什麼時候應該使用 Refs ?我們建議在以下情況下使用 refs:與第三方 DOM 庫集成觸發命令式動畫管理焦點,文本選擇或媒體播放譯註:第三點是否也可以理解為使用 event 對象呢?在 React 中就是合成事件(SyntheticEvent)。
  • 一文搞懂 React ref
    這種方式訪問 refs ,我們建議用回調函數或 createRef API 的方式代替。"例如一個第三方庫的父組件已經給子組件傳遞了 ref,那麼我們就無法再在子組件上添加 ref 了。另一方面,回調引用沒有一個所有者,因此您可以隨時編寫它們。
  • React篇(011)-React 中 refs 的作用是什麼?
    答案:refs 是 React 提供給我們的安全訪問 DOM 元素或者某個組件實例的句柄。
  • React ref 你真的懂了嗎?
    這種方式訪問 refs ,我們建議用回調函數或 createRef API 的方式代替。"例如一個第三方庫的父組件已經給子組件傳遞了 ref,那麼我們就無法再在子組件上添加 ref 了。另一方面,回調引用沒有一個所有者,因此您可以隨時編寫它們。
  • 閒庭信步聊前端 - 原來你是這樣的refs
    「福利」 ✿✿ ヽ(°▽°)ノ ✿:文章最後有抽獎,轉轉紀念 T 恤一件,走過路過不要錯過,積極留言哦一、refs 的由來什麼是refsrefs是拿到真實的DOM節點和React元素實例的一種方法。在React官方文檔中有提到Refs 提供了一種方式,允許我們訪問 DOM 節點或在 render 方法中創建的 React 元素。
  • 第299天:React中JSX的理解
    React中JSX的理解JSX是快速生成react元素的一種語法,實際是React.createElement
  • 我對 React V16.4 生命周期的理解
    這個階段的過程如下:UNSAVE_componentWillMount(React Updates DOM and refs)constructor組件的構造函數,第一個被執行。如果在組件中沒有顯示定義它,則會擁有一個默認的構造函數。
  • 【第904期】React 常見的面試題
    當調用 setState 時,React會做的第一件事情是將傳遞給 setState 的對象合併到組件的當前狀態。這將啟動一個稱為一致化處理(reconciliation)的過程。一致化處理(reconciliation)的最終目標是以最有效的方式,根據這個新的狀態來更新UI。 為此,React將構建一個新的 React 元素樹(您可以將其視為 UI 的對象表示)。
  • React源碼分析與實現(一):組件的初始化與渲染
    react最初的設計靈感來源於遊戲渲染的機制:當數據變化時,界面僅僅更新變化的部分而形成新的一幀渲染。所以設計react的核心就是認為UI只是把數據通過映射關係變換成另一種形式的數據,也就是展示方式。傳統上,web架構使用模板或者HTML指令構造頁面。
  • 【第1793期】理解 React 的下一步:Concurrent Mode 與 Suspense
    前言【第1773期】19 個來自 2019 React Conf 的總結 今日早讀文章由@林承澤分享。
  • refs - 訪問DOM或組件實例
    <div ref="sydiv">Vue的概念太多了</div>在 Vue 組件中有一個屬性 $refs,通過它可以獲取到組件實例或 DOM 元素。在 Vue 組件中,還有很多 Api。
  • 第285天:React生命周期
    ;meta charset="UTF-8" /> <title>React生命周期</title></head><body> <div id="root"></div></body><script src="https://unpkg.com/react
  • vue中的 ref 和 $refs
    引用信息將會註冊在父組件的 $refs 對象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例:<!-- `vm.$refs.p` will be the DOM node --><p ref="p">hello</p><!-- `vm.
  • 推薦11 款 React Native 開源移動 UI 組件
    攝像機視圖 react-native-camerareact-native-camera 是 React Native 的攝像頭 viewport。這個模塊應用於開發的早期階段,它支持攝像頭的轉換和基本圖片捕捉。
  • React系列六 - 父子組件通信
    那麼這個組件就會變成非常的臃腫和難以維護;所以組件化的核心思想應該是對組件進行拆分,拆分成一個個小的組件;再將這些組件組合嵌套在一起,最終形成我們的應用程式;我們來分析一下下面代碼的嵌套邏輯:import React, { Component } from 'react
  • React組件邏輯復用的那些事兒
    當然,如果你曾經在低版本的 react 中使用過 Mixins,例如 react-timer-mixin, react-addons-pure-render-mixin,那麼你可能知道,在 React 的新版本中我們其實還是可以使用 mixin,雖然 React.createClass 已經被移除了,但是仍然可以使用第三方庫 create-react-class,來繼續使用 mixin。
  • React-深入理解Props和States
    為了更好地理解,可以將整個UI看作一棵樹。在這裡,起始組件成為根,每個獨立的部分成為分支,這些分支又被進一步劃分為子分支。這使我們的UI具有組織性,並允許數據和狀態更改邏輯地從根流向分支,然後再流向子分支。組件直接從客戶端調用伺服器,這允許DOM在不刷新頁面的情況下動態更新。這是因為react組件是基於AJAX請求的概念構建的。每個組件都有自己的接口,可以調用伺服器並更新它們。
  • React開發必須知道的34個技巧
    1、組件通訊1.1道具子組件import React from "react";import PropTypes from "prop-types";import { Button } from "antd";export default class
  • 深入理解React Diff算法
    ), type: "div", key: "A" }, {$$typeof: Symbol(react.element), type: "div", key: "B" }, {$$typeof: Symbol(react.element), type: "div", key: "B" }, ]Diff的基本原則對於新舊兩種結構來說
  • React開發必須知道的34個技巧(建議收藏)
    道具子組件import React from "react";import PropTypes from "prop-types";import { Button } from "antd";export default class EightteenChildOne