AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁(yè) > 科技  > 軟件

React高手都善于使用useImprativeHandle

來(lái)源: 責(zé)編: 時(shí)間:2024-01-19 17:27:51 263觀(guān)看
導(dǎo)讀一、useRef學(xué)習(xí) useImperativeHandle,得從 useRef 說(shuō)起。我們前面已經(jīng)學(xué)習(xí)過(guò)了 useRef,它能夠結(jié)合元素組件的 ref 屬性幫我們拿到該元素組件對(duì)應(yīng)的真實(shí) DOM。例如,我想要拿到一個(gè) input 元素的真實(shí) DOM 對(duì)象,并調(diào)用 input

KPR28資訊網(wǎng)——每日最新資訊28at.com

一、useRef

學(xué)習(xí) useImperativeHandle,得從 useRef 說(shuō)起。我們前面已經(jīng)學(xué)習(xí)過(guò)了 useRef,它能夠結(jié)合元素組件的 ref 屬性幫我們拿到該元素組件對(duì)應(yīng)的真實(shí) DOM。KPR28資訊網(wǎng)——每日最新資訊28at.com

例如,我想要拿到一個(gè) input 元素的真實(shí) DOM 對(duì)象,并調(diào)用 input 的 .focus() 方法,讓 input 獲得焦點(diǎn)。KPR28資訊網(wǎng)——每日最新資訊28at.com

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}>        點(diǎn)擊我讓input組件獲得焦點(diǎn)      </button>    </>  );}

每一個(gè) React 提供的元素組件,都具備 ref 屬性。在上面的章節(jié)中我們可以知道,當(dāng)我們拿到了元素的原生 DOM 對(duì)象之后,就可以脫離 React 的開(kāi)發(fā)思路,從而應(yīng)對(duì)更多更復(fù)雜的場(chǎng)景。KPR28資訊網(wǎng)——每日最新資訊28at.com

那么問(wèn)題就來(lái)了,原生組件有自己的 ref 屬性,那么自定義組件呢?當(dāng)然是沒(méi)有的,因此我們得自己想辦法處理。KPR28資訊網(wǎng)——每日最新資訊28at.com

二、forwardRef

forwardRef 能夠在我們自定義組件時(shí),把內(nèi)部組件的 ref 屬性傳遞給父組件。KPR28資訊網(wǎng)——每日最新資訊28at.com

它接受我們自定義的組件作為參數(shù),并返回一個(gè)新的組件。新組件具備我們自定義組件的全部能力,并得到一個(gè) ref 屬性,父組件通過(guò) useRef 獲取到的內(nèi)容與內(nèi)部組件的 ref 完全一致。KPR28資訊網(wǎng)——每日最新資訊28at.com

我們來(lái)看一個(gè)案例。KPR28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在我們要實(shí)現(xiàn)如下效果,當(dāng)點(diǎn)擊 Edit 按鈕時(shí),輸入框自動(dòng)獲得焦點(diǎn)。KPR28資訊網(wǎng)——每日最新資訊28at.com

KPR28資訊網(wǎng)——每日最新資訊28at.com

我們知道,在 DOM 中,只要得到 input 對(duì)象,然后就可以調(diào)用 .focus() 方法來(lái)實(shí)現(xiàn)目標(biāo)。現(xiàn)在我們要封裝一個(gè)自定義的 MyInput 組件,他具備 input 同樣的能力,同時(shí),我們還要封裝一個(gè)標(biāo)題進(jìn)去。KPR28資訊網(wǎng)——每日最新資訊28at.com

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

我們的代碼如下:KPR28資訊網(wǎng)——每日最新資訊28at.com

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 在聲明時(shí)要傳入兩個(gè)參數(shù),一個(gè) props,一個(gè) ref。通過(guò)展開(kāi)運(yùn)算符,我們能夠確保 MyInput 支持 input 所有的屬性。KPR28資訊網(wǎng)——每日最新資訊28at.com

封裝好之后,我們就可以在點(diǎn)擊實(shí)踐中,通過(guò) ref 得到的引用去調(diào)用 .focus() 達(dá)到 input 獲取焦點(diǎn)的目標(biāo)。KPR28資訊網(wǎng)——每日最新資訊28at.com

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

在實(shí)踐中,很多時(shí)候,我們并不想通過(guò) ref 去獲取子組件內(nèi)部的某個(gè)元素組件的真實(shí) DOM 對(duì)象。而是希望父組件能夠調(diào)用子組件內(nèi)部的某些方法KPR28資訊網(wǎng)——每日最新資訊28at.com

但是在 React 中,又無(wú)法直接 new 一個(gè)子組件的實(shí)例,像面向?qū)ο竽菢油ㄟ^(guò)子組件實(shí)例去調(diào)用子組件的方法。KPR28資訊網(wǎng)——每日最新資訊28at.com

因此,React 提供了一個(gè) hook,useImperativeHandle,讓我們能夠重寫(xiě)子組件內(nèi)部 ref 對(duì)應(yīng)的引用,從而達(dá)到在父組件中,調(diào)用子組件內(nèi)部方法的目的KPR28資訊網(wǎng)——每日最新資訊28at.com

例如,上面的 MyInput 組件,我們可以修改代碼為:KPR28資訊網(wǎng)——每日最新資訊28at.com

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 接收三個(gè)參數(shù),分別是KPR28資訊網(wǎng)——每日最新資訊28at.com

  • ref: 組件聲明時(shí)傳入的 ref。
  • createHandle: 回調(diào)函數(shù),需要返回 ref 引用的對(duì)象,我們也是在這里重寫(xiě) ref 引用。
  • deps: 依賴(lài)項(xiàng)數(shù)組,可選。state,props 以及內(nèi)部定義的其他變量都可以作為依賴(lài)項(xiàng),React 內(nèi)部會(huì)使用 Object.is 來(lái)對(duì)比依賴(lài)項(xiàng)是否發(fā)生了變化。依賴(lài)項(xiàng)發(fā)生變化時(shí),createHandle 會(huì)重新執(zhí)行,ref 引用會(huì)更新。如果不傳入依賴(lài)項(xiàng),那么每次更新 createHandle 都會(huì)重新執(zhí)行。

useImperativeHandle 執(zhí)行本身返回 undefined。KPR28資訊網(wǎng)——每日最新資訊28at.com

四、官方案例

官方文檔中有這種一個(gè)案例,效果如圖所示。當(dāng)點(diǎn)擊按鈕時(shí),我希望下方的 input 自動(dòng)獲得焦點(diǎn),并切中間的滾動(dòng)條滾動(dòng)到最底部。KPR28資訊網(wǎng)——每日最新資訊28at.com

KPR28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,我們結(jié)合前面的知識(shí)來(lái)分析一下這個(gè)案例應(yīng)該如何實(shí)現(xiàn)。KPR28資訊網(wǎng)——每日最新資訊28at.com

首先我們先進(jìn)行組件拆分,將整個(gè)內(nèi)容拆分為按鈕部分與信息部分,信息部分主要負(fù)責(zé)信息的暫時(shí)與輸入,因此頁(yè)面組件大概長(zhǎng)這樣。KPR28資訊網(wǎng)——每日最新資訊28at.com

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

我們期望點(diǎn)擊按鈕時(shí),信息部分的輸入框自動(dòng)獲取焦點(diǎn),信息部分的信息展示區(qū)域能滾動(dòng)到最底部,因此整個(gè)頁(yè)面組件的代碼可以表示為如下:KPR28資訊網(wǎng)——每日最新資訊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} />    </>  );}

信息部分 Post 又分為兩個(gè)部分,分別是信息展示部分與信息輸入部分。KPR28資訊網(wǎng)——每日最新資訊28at.com

此時(shí)這兩個(gè)部分的 ref 要透?jìng)鹘o Post,并最終再次透?jìng)鹘o頁(yè)面組件。KPR28資訊網(wǎng)——每日最新資訊28at.com

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

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 的代碼為。KPR28資訊網(wǎng)——每日最新資訊28at.com

import { forwardRef, useRef, useImperativeHandle } from 'react';const AddComment = forwardRef(function AddComment(props, ref) {  return <input placeholder="Add comment..." ref={ref} />;});export default AddComment;

Post 要把他們整合起來(lái)。KPR28資訊網(wǎng)——每日最新資訊28at.com

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;

這樣,我們整個(gè)案例的代碼就寫(xiě)完了。useRef、useImprativeHandle、forwardRef 一起配合幫助我們完成了這個(gè)功能。KPR28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-65368-0.htmlReact高手都善于使用useImprativeHandle

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 從 SQLlin 的更新看 Kotlin Multiplatform 技術(shù)更迭

下一篇: Go 日期時(shí)間包裝器:15 條更便捷的時(shí)間處理

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top