日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook

發布時間:2024/7/5 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、useRef

useRef返回一個ref對象,返回的ref對象再組件的整個生命周期保持不變

最常用的ref是兩種用法:

  • 用法一:引入DOM(或者組件,但是需要是class組件)元素;
    案例一:引用DOM
import React, {useRef} from "react";class TestCpn extends React.Component{render() {return <h2>TestCpn</h2>} }function TestCpn2(props) {return <h2>TestCpn2</h2> }export default function RefHookDemo01() {const titleRef = useRef()const inputRef = useRef()const testRef = useRef()const testRef2 = useRef()function changeDOM() {titleRef.current.innerHTML = 'hello world'inputRef.current.focus()console.log(testRef.current)console.log(testRef2.current)}return (<div><h2 ref={titleRef}>RefHookDemo01</h2><input type="text" ref={inputRef}/><TestCpn ref={testRef} /><TestCpn2 ref={testRef2} /><button onClick={e => changeDOM()}>修改DOM</button></div>) }
  • 用法二:保存一個數據,這個對象在整個生命周期中可以保存不變;
    案例二:使用ref保存上一次的某一個值
import React, {useEffect, useRef, useState} from "react";export default function RefHookDemo02() {const [count, setCount] = useState(0)const numRef = useRef(count)useEffect(() => {numRef.current = count}, [count])return (<div>{/*<h2>numRef中的值: {numRef.current}</h2>*/}{/*<h2>count中的值: {count}</h2>*/}<h2>count上一次的值:{numRef.current}</h2><h2>count當前的值:{count}</h2><button onClick={e => setCount(count + 10)}>+10</button></div>) }

二、useImperativeHandle

useImperativeHandle并不是特別好理解,我們一點點來學習。

我們先來回顧一下ref和forwardRef結合使用:

  • 通過forwardRef可以將ref轉發到子組件;
  • 子組件拿到父組件中創建的ref,綁定到自己的某一個元素中;
import React, {forwardRef, useRef} from "react";const HYInput = forwardRef((props,ref) => {return <input ref={ref} type="text"/>} )export default function ForwardRefDemo() {const inputRef = useRef()return (<div><HYInput ref={inputRef}/><button onClick={e => inputRef.current.focus()}>聚焦</button></div>) }

forwardRef的做法本身沒有什么問題,但是我們是將子組件的DOM直接暴露給了父組件:

  • 直接暴露給父組件帶來的問題是某些情況的不可控;
  • 父組件可以拿到DOM后進行任意的操作;
  • 但是,事實上在上面的案例中,我們只是希望父組件可以操作的focus,其他并不希望它隨意操作;

通過useImperativeHandle可以只暴露固定的操作:

  • 通過useImperativeHandle的Hook,將傳入的ref和useImperativeHandle第二個參數返回的對象綁定到了一起;
  • 所以在父組件中,使用 inputRef.current時,實際上使用的是返回的對象
  • 比如我調用了 focus函數;
import React, {forwardRef, useImperativeHandle, useRef} from "react";const HYInput = forwardRef((props, ref) => {const inputRef = useRef()useImperativeHandle(ref, () => {return {focus: () => {inputRef.current.focus()console.log('useImperativeHandle中回調函數返回的對象里面的focus')}}}, [inputRef.current])return <input ref={inputRef} type="text"/>} )export default function ForwardRefDemo02() {const inputRef = useRef()return (<div><HYInput ref={inputRef}/><button onClick={e => inputRef.current.focus()}>聚焦</button></div>) }

三、useLayoutEffect

useLayoutEffect看起來和useEffect非常的相似,事實上他們也只有一點區別而已:

  • useEffect會在渲染的內容更新到DOM上后執行,不會阻塞DOM的更新;
  • useLayoutEffect會在渲染的內容更新到DOM上之前執行,會阻塞DOM的更新

如果我們希望在某些操作發生之后再更新DOM,那么應該將這個操作放到useLayoutEffect。
案例: useEffect和useLayoutEffect的對比


四、自定義Hook

自定義Hook本質上只是一種函數代碼邏輯的抽取,嚴格意義上來說,它本身并不算React的特性。

需求0:所有的組件在創建和銷毀時都進行打印

  • 組件被創建:打印 組件被創建了;
  • 組件被銷毀:打印 組件被銷毀了;

import React, {useEffect} from "react"; const Home = (props) => {useEffect(() => {console.log('Home組件被創建出來了~')return () => {console.log('Home組件被銷毀了!')}}, [])return <h2>Home</h2> } const Profile = (props) => {useEffect(() => {console.log('Profile組件被創建出來了~')return () => {console.log('Profile組件被銷毀了!')}}, [])return <h2>Profile</h2> } export default function CustomHookLifeDemo01() {useEffect(() => {console.log('CustomHookLifeDemo01組件被創建出來了~')return () => {console.log('CustomHookLifeDemo01組件被銷毀了!')}}, [])return (<div><h2>CustomHookLifeDemo01</h2><Home /><Profile /></div>) }

import React, {useEffect} from "react"; const Home = (props) => {useLoggingLife('Home')return <h2>Home</h2> } const Profile = (props) => {useLoggingLife('Profile')return <h2>Profile</h2> } export default function CustomHookLifeDemo01() {useLoggingLife('CustomHookLifeDemo01')return (<div><h2>CustomHookLifeDemo01</h2><Home /><Profile /></div>) } function useLoggingLife(name) {useEffect(() => {console.log(`${name}組件被創建出來了~`)return () => {console.log(`${name}組件被銷毀了!`)}}, []) }

需求一:Context的共享


import {useContext} from "react"; import {TokenContext, UserContext} from "../App";function useUserContext() {const user = useContext(UserContext)const token = useContext(TokenContext)return [user, token] }export default useUserContext

需求二:獲取鼠標滾動位置



需求三:localStorage數據存儲



總結

以上是生活随笔為你收集整理的React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。