日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

來自 React 19 的背刺:ForwardRef 被無情拋棄

來源: 責編: 時間:2024-06-21 17:25:06 255觀看
導讀在之前的版本中,forwardRef 一直是我最愛用的 ref 之一。它在封裝組件時非常有用??墒侨f萬沒想到,由于使用方式稍微麻煩了一點,在新的版本中,直接被 React 19 背刺一刀,實現同樣的功能,以后可以不用它了.... forwardRef 被

gBi28資訊網——每日最新資訊28at.com

在之前的版本中,forwardRef 一直是我最愛用的 ref 之一。它在封裝組件時非常有用。可是萬萬沒想到,由于使用方式稍微麻煩了一點,在新的版本中,直接被 React 19 背刺一刀,實現同樣的功能,以后可以不用它了.... forwardRef 被無情拋棄。gBi28資訊網——每日最新資訊28at.com

本文主要內容包括如下幾個部分。gBi28資訊網——每日最新資訊28at.com

  • React 中的 控制反轉 IOC。
  • forwardRef 基礎知識。
  • React 19 中 ref 機制更改,forwardRef 被無情拋棄。
  • useImperativeHandle 與 ref 的新配合。

一、React 中的控制反轉

在面向對象編程中,IOC (Inversion of Control) 控制反轉是一個非常高級的概念。它是一種設計理念,在減少對象之間的耦合關系上有非常重要的作用。gBi28資訊網——每日最新資訊28at.com

?gBi28資訊網——每日最新資訊28at.com

許多前端雖然對其有所耳聞,但說實話,能理解的并不多。甚至很對前端對解耦這個概念都是一頭霧水。gBi28資訊網——每日最新資訊28at.com

IOC 的設計理念里,有三個角色,一個角色是容器 C,一個角色是被控制者 B,一個角色是控制者 A,許多時候,在代碼開發中,控制者 A 直接去控制對象 B,會導致 B 被多次實例化而從讓代碼邏輯變得更加復雜。因此 IOC 的理念是讓 控制者 A 失去對 B 的直接控制權,它只能與容器交互。從而將 A 與 B 的直接聯系隔離開。gBi28資訊網——每日最新資訊28at.com

這樣說可能會有點繞,但是呢,我們使用一個大家經常使用的代碼來說明一下,你一下就能明白。gBi28資訊網——每日最新資訊28at.com

const ref = useRef()
<InputNumber ref={ref} />
ref.current.focus()

在這個案例里,我們的目標是直接獲取到 input 對象,并且調用它的 focus 方法,讓 input 獲得焦點。gBi28資訊網——每日最新資訊28at.com

var input = document.getElementById('input')input.focus()

但是在模塊的劃分上,input 元素本身并不屬于當前模塊/組件,因此,調用 input 方法的行為,其實是屬于一種混亂。除非我們不做解耦和封裝。gBi28資訊網——每日最新資訊28at.com

因此,在 React 的組件封裝中,并不支持直接獲取到 input 的引用,而是以一種傳入控制器的方式來調用它。在這個場景里:gBi28資訊網——每日最新資訊28at.com

input 對象本身是被調用者
InputNumber 組件是容器
ref 是控制器gBi28資訊網——每日最新資訊28at.com

當前組件利用 ref 來調用 input。從而讓代碼的解耦變得非常合理??蓴U展性也很強。gBi28資訊網——每日最新資訊28at.com

?gBi28資訊網——每日最新資訊28at.com

注意一些概念上的區分:控制反轉是一種設計思維,依賴注入是控制反轉的一種具體實現,在 React 中,ref 也是一種控制反轉的具體實現。gBi28資訊網——每日最新資訊28at.com

所以不要聽著別人吹控制反轉就覺得牛,你可能也天天在用。gBi28資訊網——每日最新資訊28at.com

二、forwardRef 基礎知識

forwardRef 能夠幫助 React 組件傳遞 ref?;蛘哒f是內部對象控制權的轉移與轉發。它接收一個組件作為參數。gBi28資訊網——每日最新資訊28at.com

import { forwardRef } from 'react';function MyInput(props, ref) {  // ...}const InputNumber = forwardRef(MyInput);

這里需要注意的是,我們需要把 ref 放在自定義組件的參數中。gBi28資訊網——每日最新資訊28at.com

function MyInput(props, ref) {  // ...}

forwardRef 返回一個可渲染的函數組件。因此,我們可以通過一個簡單的案例完善上面的代碼。gBi28資訊網——每日最新資訊28at.com

function MyInput(props, ref) {  return (    <label>      {props.label}      <input ref={ref} />    </label>  );}const InputNumber = forwardRef(MyInput)

所以呢,在 React 的開發中,forwardRef 能夠幫助我們實現更良好的解耦,這也是我一直非常喜歡使用 forwardRef 的原因。gBi28資訊網——每日最新資訊28at.com

三、ref 機制更改,forwardRef 被無情拋棄

但是,在 React 19 中,forwardRef 被直接背刺,由于 ref 傳遞機制的更改,我們可以不用 forwardRef 也能做到同樣的事情了。gBi28資訊網——每日最新資訊28at.com

首先,在聲明組件時,ref 不再獨立成為一個參數,而是作為 props 屬性中的一個屬性。gBi28資訊網——每日最新資訊28at.com

function MyInput(props) {  return (    <label>      {props.label}      <input ref={props.ref} />    </label>  );}

其次,代碼這樣寫了之后,就可以直接在父組件中,通過 ref 拿到 input 的控制權。gBi28資訊網——每日最新資訊28at.com

function Index() {  const input = useRef(null)  function __clickHandler() {    input.current.focus()  }  return (    <div>      <button onClick={__clickHandler}>        點擊獲取焦點      </button>      <MyInput ref={input} />    </div>  )}

在父組件中的使用與以前一樣,但是子組件由于不再需要 forwardRef,變得更加簡單了。gBi28資訊網——每日最新資訊28at.com

四、useImperativeHandle 與 ref 的新配合

除了直接拿到元素對象本身就已經存在的 ref,我們還可以通過 useImperativeHandle 來自定義 ref 控制器能執行哪些方法gBi28資訊網——每日最新資訊28at.com

useImperativeHandle 接收三個參數,分別是:gBi28資訊網——每日最新資訊28at.com

  • ref: 組件聲明時傳入的 ref。
  • createHandle: 回調函數,需要返回 ref 引用的對象,我們也是在這里重寫 ref 引用。
  • deps: 依賴項數組,可選。state,props 以及內部定義的其他變量都可以作為依賴項,React 內部會使用 Object.is 來對比依賴項是否發生了變化。依賴項發生變化時,createHandle 會重新執行,ref 引用會更新。如果不傳入依賴項,那么每次更新 createHandle 都會重新執行。

在官方文檔中,有這樣一個案例,演示效果如圖所示,當我點擊按鈕時,下方的 input 自動獲取焦點,并且中間的滾動條滾動到最底部。gBi28資訊網——每日最新資訊28at.com

gBi28資訊網——每日最新資訊28at.com

我們結合新的 ref 傳遞機制和 useImperativeHandle 一起來分析一下這個案例應該怎么實現。gBi28資訊網——每日最新資訊28at.com

!gBi28資訊網——每日最新資訊28at.com

思考時,請一定要把封裝的思維帶入進來,否則可能很難感受到這樣做在解耦上的具體好處gBi28資訊網——每日最新資訊28at.com

首先我們先進行組件拆分,將整個內容拆分為按鈕部分與信息部分,信息部分主要負責信息的展示與輸入,因此頁面組件大概長這樣gBi28資訊網——每日最新資訊28at.com

<>  <button>Write a comment</button>  <Post /></>

我們期望點擊按鈕時,信息部分的輸入框自動獲取焦點,信息部分的信息展示區域能滾動到最底部,因此整個頁面組件的代碼可以表示為如下:gBi28資訊網——每日最新資訊28at.com

import { useRef } from 'react';import Post from './Post.js';export default function Page() {  const postRef = useRef(null);  function handleClick() {    postRef.current.scrollAndFocusAddComment();  }  return (    <>      <button onClick={handleClick}>        Write a comment      </button>      <Post ref={postRef} />    </>  );}

再來思考信息部分。gBi28資訊網——每日最新資訊28at.com

信息部分 Post 又分為兩個部分,分別是信息展示部分與信息輸入部分。此時這兩個部分的 ref 要透傳給 Post,并最終再次透傳給頁面組件。因此他們的組件結構應該長這樣。gBi28資訊網——每日最新資訊28at.com

<>  <article>    <p>Welcome to my blog!</p>  </article>  <CommentList ref={commentsRef} />  <AddComment ref={addCommentRef} /></>

這個時候,有一個需要考慮的點就是,有兩個對象需要被控制,因此我們需要借助 useImperativeHandle 來自定義控制器,并在控制的方法中,整合他們。gBi28資訊網——每日最新資訊28at.com

useImperativeHandle(ref, () => {  return {    scrollAndFocusAddComment() {      commentsRef.current.scrollToBottom();      addCommentRef.current.focus();    }  };}, []);

ref 的傳遞,只需要把它看成是一個普通的 props 即可,因此,Post 組件完整代碼如下:gBi28資訊網——每日最新資訊28at.com

const Post = ({ref}) => {  const commentsRef = useRef(null);  const addCommentRef = useRef(null);  useImperativeHandle(ref, () => {    return {      scrollAndFocusAddComment() {        commentsRef.current.scrollToBottom();        addCommentRef.current.focus();      }    };  }, []);  return (    <>      <article>        <p>Welcome to my blog!</p>      </article>      <CommentList ref={commentsRef} />      <AddComment ref={addCommentRef} />    </>  );}

同樣的道理,我們只需要把 CommentList 與 AddComment 的 ref 傳遞出來就可以了。gBi28資訊網——每日最新資訊28at.com

所以信息展示部分 CommentList 組件的代碼為。gBi28資訊網——每日最新資訊28at.com

import { useRef, useImperativeHandle } from 'react';const CommentList = ({ref}) => {  const divRef = useRef(null);  useImperativeHandle(ref, () => {    return {      scrollToBottom() {        const node = divRef.current;        node.scrollTop = node.scrollHeight;      }    };  }, []);  let comments = [];  for (let i = 0; i < 50; i++) {    comments.push(<p key={i}>Comment #{i}</p>);  }  return (    <div className="CommentList" ref={divRef}>      {comments}    </div>  );};export default CommentList;

信息輸入部分 AddComment 的代碼為。gBi28資訊網——每日最新資訊28at.com

function AddComment(props) {  return (    <input       placeholder="Add comment..."       ref={props.ref}     />  )};export default AddComment;

與之前相比,確實要簡單了許多。gBi28資訊網——每日最新資訊28at.com

五、總結

如果你對封裝解耦比較重視,那么你一定能明顯感受到,ref 與 useImperativeHandle 的結合能發揮的想象空間遠不止于此,這種方式給 React 提供了一種擴展 React 能力的重要手段,因此,當你成為 React 高手之后,你一定會非常喜歡使用它們,他們的組合能讓 React 項目變得更加多樣化。gBi28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-95554-0.html來自 React 19 的背刺:ForwardRef 被無情拋棄

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 幾行代碼,優雅的避免接口重復請求

下一篇: 如何更改 .NET 中的默認時區?

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
久久精品一本| 日韩一区二区电影网| 国产亚洲欧美一区在线观看| 国产一区二区三区自拍| 亚洲高清视频的网址| av成人老司机| 欧美在线日韩精品| 欧美va天堂在线| 欧美午夜电影一区| 国产亚洲一区二区三区| 亚洲国产色一区| 亚洲午夜精品一区二区| 久久国产欧美精品| 欧美激情久久久| 国产伦理一区| 亚洲欧洲在线看| 欧美一区二区三区电影在线观看| 你懂的视频欧美| 国产精品―色哟哟| 亚洲韩日在线| 欧美日韩另类综合| 国产欧美一区二区三区在线老狼 | 激情久久五月天| 一本在线高清不卡dvd | 久久久人成影片一区二区三区观看| 欧美寡妇偷汉性猛交| 国产精品乱人伦中文| 亚洲第一视频网站| 亚洲欧美日韩网| 欧美高清视频在线播放| 国产日韩精品一区| 99亚洲一区二区| 狂野欧美激情性xxxx欧美| 国产精品久久久久久久一区探花 | 欧美精品在线观看| 狠狠色伊人亚洲综合成人| 亚洲视频精品| 欧美韩国日本一区| 激情六月婷婷综合| 亚洲免费在线观看| 欧美人成网站| 亚洲国产高清一区| 久久不射2019中文字幕| 欧美性大战久久久久久久蜜臀| 亚洲福利专区| 久久精品亚洲精品| 国产精品女人毛片| 中文精品99久久国产香蕉| 牛牛国产精品| 在线日韩精品视频| 久久久999精品| 国产欧美一区视频| 亚洲综合另类| 欧美色欧美亚洲另类七区| 最新国产精品拍自在线播放| 久久久久国产精品午夜一区| 国产精品亚洲综合久久| 中文高清一区| 欧美色图一区二区三区| 日韩一区二区精品葵司在线| 欧美大香线蕉线伊人久久国产精品| 伊人久久婷婷| 久久综合久久综合这里只有精品| 国内精品久久久久影院优| 欧美在线影院| 国产在线高清精品| 欧美在线观看视频一区二区| 国产精品嫩草影院一区二区| 亚洲制服丝袜在线| 国产精品magnet| 亚洲午夜精品久久久久久app| 欧美日韩精品免费观看视频完整| 亚洲精品日韩综合观看成人91| 欧美二区视频| 亚洲精品色婷婷福利天堂| 欧美成人一区二区三区| 亚洲经典在线| 欧美激情精品久久久| 亚洲人体一区| 欧美日韩亚洲91| 亚洲天堂久久| 国产精品大片免费观看| 亚洲免费影院| 国产精品自在欧美一区| 欧美一区永久视频免费观看| 国产视频久久| 久久久精品国产免费观看同学| 国语精品一区| 男同欧美伦乱| 亚洲精选大片| 欧美婷婷久久| 欧美亚洲三区| 黄色亚洲免费| 欧美国产日韩一区| 在线一区二区三区做爰视频网站| 国产精品福利在线| 久久av一区二区三区漫画| 国内精品久久久久久久影视蜜臀| 久久亚洲欧美| 亚洲黑丝一区二区| 国产精品成人一区二区三区夜夜夜 | 亚洲在线成人| 国产亚洲精品激情久久| 久久嫩草精品久久久久| 亚洲黄色免费电影| 欧美色另类天堂2015| 欧美亚洲免费电影| 伊人蜜桃色噜噜激情综合| 欧美电影在线观看| 亚洲制服欧美中文字幕中文字幕| 国产亚洲精品久久飘花| 欧美成人午夜视频| 亚洲一级一区| 国内一区二区在线视频观看 | 国产精品美女久久久久av超清| 欧美在线亚洲在线| 亚洲国产一二三| 国产精品国产三级国产普通话99| 欧美一区=区| 亚洲国产乱码最新视频| 欧美日韩中文字幕精品| 午夜精品亚洲| 亚洲国产一区二区三区高清 | 精品动漫一区二区| 欧美日本在线观看| 午夜视频在线观看一区二区三区| 精品成人乱色一区二区| 欧美日韩亚洲视频一区| 久久国产精品第一页| 亚洲精品视频在线观看免费| 国产精品裸体一区二区三区| 久久免费视频这里只有精品| 一本色道久久综合亚洲91| 黑人一区二区三区四区五区| 欧美日韩精品在线| 久久美女性网| 亚洲午夜精品久久久久久浪潮| 在线不卡中文字幕| 国产精品一级| 欧美激情精品久久久久久免费印度 | 亚洲网站视频福利| 影音先锋日韩资源| 国产精品久久久久7777婷婷| 久久一区二区三区av| 亚洲网站在线播放| 亚洲黄页视频免费观看| 国产麻豆9l精品三级站| 欧美精品一区二区三| 久久国产夜色精品鲁鲁99| 一本色道久久综合亚洲精品高清| 狠狠色狠狠色综合日日小说| 国产精品国产亚洲精品看不卡15 | 亚洲图片你懂的| 亚洲黄色av一区| 国产亚洲精久久久久久| 欧美三级乱人伦电影| 你懂的视频一区二区| 欧美在线亚洲综合一区| 亚洲亚洲精品三区日韩精品在线视频 | 国产在线精品一区二区夜色| 国产精品xnxxcom| 欧美成人精品激情在线观看| 欧美中文在线字幕| 亚洲一区在线免费观看| 亚洲精品三级| 亚洲成人在线视频网站| 国产在线乱码一区二区三区| 国产精品婷婷| 国产精品va在线| 欧美久久久久免费| 欧美成人精品福利| 久久久久久精| 欧美在线视频免费观看| 亚洲一级影院| 一区二区三区日韩精品| 亚洲日本成人女熟在线观看| 悠悠资源网亚洲青| 国内成人精品一区| 国产欧美精品在线播放| 国产精品久久久久久久久久尿| 欧美国产免费| 欧美国产日韩一二三区| 欧美bbbxxxxx| 噜噜噜久久亚洲精品国产品小说| 欧美在线观看视频| 久久不见久久见免费视频1| 午夜精品久久久久| 亚洲欧美视频在线| 亚洲欧美日韩中文视频| 亚洲专区在线| 亚洲在线成人精品| 亚洲欧美日韩直播| 欧美一级在线播放| 久久成人免费网| 久久精品91久久久久久再现| 久久国产精品久久久久久| 久久不射2019中文字幕| 久久国产婷婷国产香蕉| 久久久久欧美精品| 久久天天躁狠狠躁夜夜av| 久久亚洲视频| 奶水喷射视频一区| 欧美极品色图| 欧美日韩免费观看一区|