精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

React高手都善于使用useImprativeHandle

開發 前端
在 React Hooks 中,useImperativeHandle 是一個非常簡單的 Hook,他比較小眾,剛開始接觸 React 學習的朋友可能并不熟悉他。不過對于 React 頂尖高手而言,這是非常重要的 Hook,他能讓我們對 React 的使用變得更加得心應手。應對更多更復雜的場景。

一、useRef

學習 useImperativeHandle,得從 useRef 說起。我們前面已經學習過了 useRef,它能夠結合元素組件的 ref 屬性幫我們拿到該元素組件對應的真實 DOM。

例如,我想要拿到一個 input 元素的真實 DOM 對象,并調用 input 的 .focus() 方法,讓 input 獲得焦點。

import {useRef} from "react";

export default function Demo() {
  const inputRef = useRef<HTMLInputElement>(null);

  const focusTextInput = () => {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }

  return (
    <>
      <input type="text" ref={inputRef} />
      <button onClick={focusTextInput}>
        點擊我讓input組件獲得焦點
      </button>
    </>
  );
}

每一個 React 提供的元素組件,都具備 ref 屬性。在上面的章節中我們可以知道,當我們拿到了元素的原生 DOM 對象之后,就可以脫離 React 的開發思路,從而應對更多更復雜的場景。

那么問題就來了,原生組件有自己的 ref 屬性,那么自定義組件呢?當然是沒有的,因此我們得自己想辦法處理。

二、forwardRef

forwardRef 能夠在我們自定義組件時,把內部組件的 ref 屬性傳遞給父組件。

它接受我們自定義的組件作為參數,并返回一個新的組件。新組件具備我們自定義組件的全部能力,并得到一個 ref 屬性,父組件通過 useRef 獲取到的內容與內部組件的 ref 完全一致。

我們來看一個案例。

現在我們要實現如下效果,當點擊 Edit 按鈕時,輸入框自動獲得焦點。

我們知道,在 DOM 中,只要得到 input 對象,然后就可以調用 .focus() 方法來實現目標。現在我們要封裝一個自定義的 MyInput 組件,他具備 input 同樣的能力,同時,我們還要封裝一個標題進去。

<label>Enter your name</label>
<input />

我們的代碼如下:

import {forwardRef, LegacyRef} from 'react'

type MyInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
  label: string
}

function MyInput(props: MyInputProps, ref: LegacyRef<HTMLInputElement>) {
  const {label, ...other} = props

  return (
    <label>
      {label}
      <input {...other} ref={ref} />
    </label>
  )
}

export default forwardRef(MyInput)

MyInput 在聲明時要傳入兩個參數,一個 props,一個 ref。通過展開運算符,我們能夠確保 MyInput 支持 input 所有的屬性。

封裝好之后,我們就可以在點擊實踐中,通過 ref 得到的引用去調用 .focus() 達到 input 獲取焦點的目標。

import { useRef } from 'react'
import MyInput from './MyInput'

export default function ImperativeHandle() {
  const ref = useRef<any>(null)

  function handleClick() {
    ref.current?.focus()
  }

  return (
    <form>
      <MyInput 
        label='Enter your name:' 
        ref={ref} 
      />
      <button type='button' onClick={handleClick}>Edit</button>
    </form>
  )
}

三、useImperativeHandle

在實踐中,很多時候,我們并不想通過 ref 去獲取子組件內部的某個元素組件的真實 DOM 對象。而是希望父組件能夠調用子組件內部的某些方法

但是在 React 中,又無法直接 new 一個子組件的實例,像面向對象那樣通過子組件實例去調用子組件的方法。

因此,React 提供了一個 hook,useImperativeHandle,讓我們能夠重寫子組件內部 ref 對應的引用,從而達到在父組件中,調用子組件內部方法的目的

例如,上面的 MyInput 組件,我們可以修改代碼為:

import {forwardRef, useImperativeHandle, useRef} from 'react'

type MyInputProps = React.InputHTMLAttributes<HTMLInputElement> & {
  label: string
}

function MyInput(props: MyInputProps, ref: any) {
  const {label, ...other} = props
  const inputRef = useRef<any>(null)

  useImperativeHandle(ref, () => {
    return {
      focus() {
        inputRef.current.focus()
      }
    }
  }, [])

  return (
    <label>
      {label}
      <input {...other} ref={inputRef} />
    </label>
  )
}

export default forwardRef(MyInput)
useImperativeHandle(
  ref, 
  createHandle, 
  dependencies?
)

useImperativeHandle 接收三個參數,分別是

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

useImperativeHandle 執行本身返回 undefined。

四、官方案例

官方文檔中有這種一個案例,效果如圖所示。當點擊按鈕時,我希望下方的 input 自動獲得焦點,并切中間的滾動條滾動到最底部。

現在,我們結合前面的知識來分析一下這個案例應該如何實現。

首先我們先進行組件拆分,將整個內容拆分為按鈕部分與信息部分,信息部分主要負責信息的暫時與輸入,因此頁面組件大概長這樣。

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

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

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

信息部分 Post 又分為兩個部分,分別是信息展示部分與信息輸入部分。

此時這兩個部分的 ref 要透傳給 Post,并最終再次透傳給頁面組件。

所以信息展示部分 CommentList 組件的代碼為。

import { forwardRef, useRef, useImperativeHandle } from 'react';

const CommentList = forwardRef(function CommentList(props, 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 的代碼為。

import { forwardRef, useRef, useImperativeHandle } from 'react';

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

export default AddComment;

Post 要把他們整合起來。

import { forwardRef, useRef, useImperativeHandle } from 'react';
import CommentList from './CommentList.js';
import AddComment from './AddComment.js';

const Post = forwardRef((props, 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} />
    </>
  );
});

export default Post;

這樣,我們整個案例的代碼就寫完了。useRef、useImprativeHandle、forwardRef 一起配合幫助我們完成了這個功能。

責任編輯:姜華 來源: 這波能反殺
相關推薦

2013-03-18 09:30:14

大數據IT

2020-05-29 10:18:58

python開發代碼

2023-12-20 14:48:26

2024-01-16 08:43:51

React底層機制Hook

2024-02-05 21:48:25

VueReactHooks

2018-05-25 15:10:14

360手機衛士

2011-05-26 10:04:30

程序員

2009-07-16 13:51:43

2018-03-15 09:07:37

手機垃圾文件清理

2022-04-18 17:28:14

React前端

2024-01-25 09:04:25

2024-02-26 12:10:37

2022-04-08 10:15:29

VueReacHooks

2024-02-01 09:05:30

ContextReact性能優化

2011-05-16 16:59:41

SEO

2009-04-15 10:49:01

木馬釋放器卡巴斯基

2023-11-09 16:20:32

Vue.jsReact前端

2019-11-07 21:41:21

AndroidiOS不同

2024-12-06 08:00:51

2009-12-29 15:32:01

架構師
點贊
收藏

51CTO技術棧公眾號

亚洲午夜精品久久久久久久久| 久久亚洲国产精品一区二区| 日韩精品影音先锋| 国产91xxx| 成年人的黄色片| 爱情岛论坛vip永久入口| 精品无码免费视频| 欧美一区电影| 精品国产百合女同互慰| 亚洲成人av免费看| 国产精品探花在线| 日本欧美一区二区在线观看| 亚洲国产小视频在线观看| 国产真实乱子伦| a级在线观看| 国产三级欧美三级日产三级99| 亚洲综合在线做性| japanese国产在线观看| 亚洲电影成人| 久久天天躁夜夜躁狠狠躁2022| 黄色短视频在线观看| 国产精品1区| 国产精品网站导航| 国产综合动作在线观看| 欧美成人一区二区视频| 精品日本12videosex| 精品av综合导航| 91日韩精品视频| 欧美大胆性生话| 久久久精品黄色| 国产伦精品一区| 国产日韩一级片| 蜜桃视频第一区免费观看| 91高清免费视频| 久久影院一区二区| 欧美日韩1080p| 欧美va日韩va| www激情五月| 亚洲精品三区| 亚洲精品你懂的| 91色琪琪电影亚洲精品久久| 真实的国产乱xxxx在线91| 国产日韩欧美| 97久久久免费福利网址| 欧美成人手机视频| 亚洲91视频| 久久精品2019中文字幕| 免费高清在线观看电视| 久久精品青草| 伦伦影院午夜日韩欧美限制| 亚洲欧美精品久久| 亚洲成人tv| 久久香蕉国产线看观看av| 激情五月激情综合| 婷婷综合激情| 九九久久久久99精品| 中文字幕手机在线观看| 一区二区三区四区日韩| 欧美理论电影在线播放| 国产精品成人免费观看| 黄色在线成人| 欧美在线观看网站| 99久久久无码国产精品免费蜜柚| 日韩激情一区二区| 国产精品99一区| 伊人网中文字幕| 国产一区二区三区美女| 翡翠波斯猫1977年美国| 午夜18视频在线观看| 2024国产精品| 无码免费一区二区三区免费播放| 日本在线看片免费人成视1000| 国产精品视频yy9299一区| 国产奶头好大揉着好爽视频| 啪啪免费视频一区| 欧美视频在线观看免费| 中文字幕视频在线免费观看| 国产精品久久久久久久久久辛辛 | 亚洲性xxxx| jizzzz日本| 在线观看亚洲精品福利片| 日韩一区二区三区在线视频| 制服丝袜在线第一页| 亚洲人成网站77777在线观看| 在线观看欧美日韩国产| 中文在线观看免费视频| 猛男gaygay欧美视频| 色yeye香蕉凹凸一区二区av| 免费一级片视频| 肉肉av福利一精品导航| 69堂成人精品视频免费| 色在线免费视频| 亚洲天堂免费看| www一区二区www免费| eeuss中文| 国产区在线视频| 亚洲激情第一区| 国产日韩一区二区在线观看| 未满十八勿进黄网站一区不卡| 日韩免费电影一区| 性猛交ⅹxxx富婆video| 欧美精选一区| 国产精品专区一| 蜜臀久久精品久久久久| 中文字幕不卡在线播放| 免费拍拍拍网站| av片哪里在线观看| 一本在线高清不卡dvd| 亚洲天堂网站在线| 精品毛片免费观看| 欧美夜福利tv在线| 不卡视频免费在线观看| 中文字幕精品三区| 欧美丰满熟妇bbbbbb百度| 久久影院一区二区三区| 原创国产精品91| 人人干人人干人人干| 国产一区二区三区四| 日韩免费中文专区| 在线一区av| 日韩国产在线看| 国产在线观看免费视频今夜| 精品亚洲成av人在线观看| 91久久久久久| 国产精品二线| 欧美日韩中文字幕在线| 中文字幕天堂av| 欧美精品一线| 99国内精品久久久久久久软件| 97电影在线| 欧美影院午夜播放| 亚洲区自拍偷拍| 久久精品卡一| 免费久久99精品国产自| www.91在线| 色av一区二区| 这里只有久久精品| 免费国产自线拍一欧美视频| 狠狠色噜噜狠狠狠狠色吗综合| 蜜臀av在线| 精品久久99ma| 国产午夜视频在线播放| 岛国一区二区在线观看| 久久艹国产精品| jazzjazz国产精品久久| 欧美极品少妇xxxxⅹ裸体艺术| 亚洲AV无码一区二区三区性| 99久免费精品视频在线观看 | 欧美1区2区视频| 91欧美精品午夜性色福利在线 | 中文字幕一区视频| 第一区免费在线观看| 小说区亚洲自拍另类图片专区| 成人午夜在线影院| 3d玉蒲团在线观看| 欧美mv日韩mv国产网站app| 精品无码av在线| 91在线视频播放地址| 男人操女人免费软件| 色综合综合网| 成人h视频在线| 污污的网站在线免费观看| 精品电影一区二区| 国产精品第9页| 久久久国产精华| 日日噜噜夜夜狠狠| 在线中文一区| 国内精品二区| 91p九色成人| 美日韩精品视频免费看| 丰满大乳国产精品| 欧美日韩亚洲精品一区二区三区| 精品日韩久久久| 国产精品久久久久久久| 成人av免费在线看| 性爽视频在线| 久久精品小视频| 日韩中文字幕观看| 在线看不卡av| 精品99在线观看| 久久综合色综合88| www.亚洲自拍| 亚洲一区二区成人| 宅男在线精品国产免费观看| 国产成人一二片| 国产精品视频公开费视频| 性欧美高清come| 亚洲精品综合精品自拍| 日韩av在线播| 中文字幕在线不卡| 亚洲国产精品自拍视频| 久久国产福利国产秒拍| 男人的天堂狠狠干| 国产精品久久久久久久免费观看| 国产精品中出一区二区三区| 福利一区和二区| 国产精品成人a在线观看| 亚洲a在线播放| 成人影院大全| 欧美黑人性视频| 亚洲网站在线免费观看| 一区二区免费看| 亚洲精品乱码久久久久久动漫| 激情综合亚洲| 伊人久久大香线蕉精品 | 鲁丝片一区二区三区| 9999精品视频| 国产精品av免费在线观看| 啦啦啦中文在线观看日本| 中文字幕久久亚洲| 手机福利在线| 日韩色视频在线观看| 中文字幕av第一页| 黑人巨大精品欧美一区免费视频| www.超碰在线观看| 欧美国产国产综合| 色噜噜在线观看| 成人精品国产福利| 中文字幕55页| 久久99久久久久久久久久久| 国产成人精品无码播放| 国产欧美在线| 免费在线观看视频a| 欧美在线亚洲| 精品少妇人妻av一区二区| 日韩不卡一区| 色综合影院在线观看| 久操成人av| 欧美成人第一区| 神马香蕉久久| 精品久久久久久一区| 精品精品国产毛片在线看| 97久久精品视频| 欧美hdxxxxx| 欧美大片第1页| 50度灰在线| 欧美黄色片在线观看| 手机在线免费观看av| 欧美成人激情在线| 日本无删减在线| 欧美激情第1页| 888av在线视频| 亚洲日韩中文字幕在线播放| 五月婷婷六月丁香| 精品亚洲精品福利线在观看| 青青草免费在线| 亚洲人成电影网站| 国产精品99999| 一区二区三区动漫| www.亚洲免费| 按摩亚洲人久久| 偷拍精品一区二区三区| 亚洲精品一区二区三区福利 | 亚洲91在线| 成人写真视频福利网| 欧美成人精品午夜一区二区| 操人视频欧美| 日韩极品在线| 色一情一区二区三区四区 | 久久精品人人爽人人爽| 微拍福利一区二区| 国产精品福利一区| 久久久久久久久久久97| 精品高清一区二区三区| 国产一区二区视频免费| 欧美日韩视频一区二区| 国产富婆一级全黄大片| 亚洲国产日韩精品在线| 国产三级视频在线播放线观看| 日韩中文字幕在线免费观看| 亚洲图区一区| 欧美一区第一页| 欧美成人福利| 国产精品三区四区| 精品日韩免费| 国产欧美精品aaaaaa片| 老司机一区二区三区| 国产亚洲视频一区| 99久久99久久免费精品蜜臀| 91成人精品一区二区| 亚洲精品免费在线观看| 久久夜靖品2区| 欧美高清性hdvideosex| 天堂成人在线视频| 欧美一级二级在线观看| 天天综合网在线观看| 中文字幕在线观看亚洲| 国产福利在线免费观看| 国产精品久久久久秋霞鲁丝 | 欧美二区在线| 一区二区三区在线电影| 成人免费在线小视频| 国产一区三区三区| 亚洲av无码一区二区三区人| 亚洲男女毛片无遮挡| 久久久黄色大片| 欧美日韩免费一区| 91久久久久久久久久久久| 亚洲国产日韩一区| 大片免费在线观看| 国产国语刺激对白av不卡| 午夜视频一区二区在线观看| 成人久久久久爱| 日韩精品免费一区二区三区竹菊| 亚洲一区bb| 亚洲欧美激情诱惑| 佐佐木明希电影| 中文字幕在线不卡视频| 区一区二在线观看| 亚洲国产日韩欧美综合久久| 午夜伦理大片视频在线观看| 国产精品草莓在线免费观看| 老司机aⅴ在线精品导航| 色乱码一区二区三区熟女| 国产高清中文字幕| 欧美小视频在线| 亚洲第一视频在线| 波霸ol色综合久久| 日韩不卡视频在线观看| 国产一区二区视频在线免费观看| 亚洲精品中文字幕乱码| 中文字幕第21页| 2020日本不卡一区二区视频| 国产精品18p| 欧美大肚乱孕交hd孕妇| 老司机av在线免费看| 色偷偷91综合久久噜噜| 韩国美女久久| 美女被啪啪一区二区| 99在线精品视频在线观看| 女同性αv亚洲女同志| 亚洲色大成网站www久久九九| 中文字幕一区二区三区人妻四季 | 国产精品分类| 69久久精品无码一区二区| 亚洲欧美自拍偷拍| 亚洲性在线观看| 中文字幕精品在线视频| 精品国产欧美日韩一区二区三区| 欧美日韩国产精品一区二区| 亚洲在线电影| 超碰男人的天堂| 欧美日韩加勒比精品一区| 日本黄色三级视频| 98精品在线视频| 亚洲自拍电影| 亚洲一二三区av| 国产精品乱人伦中文| 一级黄色片免费| 蜜臀久久99精品久久久久久宅男 | 久久精品国产99精品国产亚洲性色| 天堂日韩电影| 国模吧无码一区二区三区| 91丝袜国产在线播放| 51国产偷自视频区视频| 亚洲图片欧美午夜| 国产成人a视频高清在线观看| 亚洲一区二区三区欧美| 国产自产v一区二区三区c| 免费视频一二三区| 日韩av有码在线| 日韩新的三级电影| 在线视频不卡一区二区| 国产一区二区三区蝌蚪| 国产中文字幕免费| 日韩精品在线观| 欧美香蕉视频| 午夜啪啪免费视频| 成人午夜视频在线| 天天干天天操天天爱| 日韩性生活视频| 99精品中文字幕在线不卡| heyzo国产| 国产精品免费丝袜| 亚洲欧美强伦一区二区| 青青草精品毛片| 98精品视频| yjizz视频| 欧美性生活大片视频| 在线播放免费av| 久久影院理伦片| 极品尤物av久久免费看| 日韩av在线电影| xxxxxxxxx欧美| 欧美日韩导航| 亚洲视频一二三四| 午夜精品久久久久久久久| av一区在线观看| 成人自拍爱视频| 蜜臀av性久久久久蜜臀aⅴ四虎| 欧美日韩在线视频免费| 亚洲欧美视频在线| 日本一区二区三区电影免费观看| 日本毛片在线免费观看| 日韩美女视频一区| 欧美欧美欧美| 国产精品久久久久久久久久久久午夜片| 久久资源在线| 精品无码久久久久久久| 日韩一区二区久久久|