最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript中ahooks?處理?DOM?的方法

 更新時(shí)間:2022年06月22日 09:47:41   作者:Gopal  
這篇文章主要介紹了JavaScript中ahooks處理DOM的方法,主要通過(guò)ahooks對(duì)DOM類Hooks使用規(guī)范,以及源碼中是如何去做處理的,具體詳細(xì)介紹需要的小伙伴可以參考一下下面文章內(nèi)容

前言

目標(biāo)主要有以下幾點(diǎn):

  • 加深對(duì) React hooks 的理解。
  • 學(xué)習(xí)如何抽象自定義 hooks。構(gòu)建屬于自己的 React hooks 工具庫(kù)。
  • 培養(yǎng)閱讀學(xué)習(xí)源碼的習(xí)慣,工具庫(kù)是一個(gè)對(duì)源碼閱讀不錯(cuò)的選擇。

本篇文章探討一下 ahooks 對(duì) DOM 類 Hooks 使用規(guī)范,以及源碼中是如何去做處理的。

DOM 類 Hooks 使用規(guī)范

這一章節(jié),大部分參考官方文檔的 DOM 類 Hooks 使用規(guī)范。

第一點(diǎn),ahooks 大部分 DOM 類 Hooks 都會(huì)接收 target 參數(shù),表示要處理的元素。

target 支持三種類型 React.MutableRefObject(通過(guò) useRef 保存的 DOM)、HTMLElement、() => HTMLElement(一般運(yùn)用于 SSR 場(chǎng)景)。

第二點(diǎn),DOM 類 Hooks 的 target 是支持動(dòng)態(tài)變化的。

如下所示:

export default () => {
  const [boolean, { toggle }] = useBoolean();

  const ref = useRef(null);
  const ref2 = useRef(null);

  const isHovering = useHover(boolean ? ref : ref2);
  return (
    <>
      <div ref={ref}>{isHovering ? 'hover' : 'leaveHover'}</div>
      <div ref={ref2}>{isHovering ? 'hover' : 'leaveHover'}</div>
    </>
  );
};

那 ahooks 是怎么處理這兩點(diǎn)的呢?

getTargetElement

獲取到對(duì)應(yīng)的 DOM 元素,這一點(diǎn)主要兼容以上第一點(diǎn)的入?yún)⒁?guī)范。

  • 假如是函數(shù),則取執(zhí)行完后的結(jié)果。
  • 假如擁有 current 屬性,則取 current 屬性的值,兼容 React.MutableRefObject 類型。
  • 最后就是普通的 DOM 元素。
export function getTargetElement<T extends TargetType>(target: BasicTarget<T>, defaultElement?: T) {
  // 省略部分代碼...
  let targetElement: TargetValue<T>;
  if (isFunction(target)) {
    // 支持函數(shù)獲取
    targetElement = target();
    // 假如 ref,則返回 current
  } else if ('current' in target) {
    targetElement = target.current;
    // 支持 DOM
  } else {
    targetElement = target;
  }

  return targetElement;
}

useEffectWithTarget

這個(gè)方法,主要是為了支持第二點(diǎn),支持 target 動(dòng)態(tài)變化。

其中 packages/hooks/src/utils/useEffectWithTarget.ts 是使用 useEffect。

import { useEffect } from 'react';
import createEffectWithTarget from './createEffectWithTarget';
const useEffectWithTarget = createEffectWithTarget(useEffect);
export default useEffectWithTarget;

另外 其中 packages/hooks/src/utils/useLayoutEffectWithTarget.ts 是使用 useLayoutEffect。

import { useLayoutEffect } from 'react';
import createEffectWithTarget from './createEffectWithTarget';
const useEffectWithTarget = createEffectWithTarget(useLayoutEffect);
export default useEffectWithTarget;

兩者都是調(diào)用的 createEffectWithTarget,只是入?yún)⒉煌?/p>

直接重點(diǎn)看這個(gè) createEffectWithTarget 函數(shù):

  • createEffectWithTarget 返回的函數(shù) useEffectWithTarget 接受三個(gè)參數(shù),前兩個(gè)跟 useEffect 一樣,第三個(gè)就是 target。
  • useEffectType 就是 useEffect 或者 useLayoutEffect。注意這里調(diào)用的時(shí)候,沒(méi)傳第二個(gè)參數(shù),也就是每次都會(huì)執(zhí)行
  • hasInitRef 判斷是否已經(jīng)初始化。lastElementRef 記錄的是最后一次 target 元素的列表。lastDepsRef 記錄的是最后一次的依賴。unLoadRef 是執(zhí)行完 effect 函數(shù)(對(duì)應(yīng)的就是 useEffect 中的 effect 函數(shù))的返回值,在組件卸載的時(shí)候執(zhí)行。
  • 第一次執(zhí)行的時(shí)候,執(zhí)行相應(yīng)的邏輯,并記錄下最后一次執(zhí)行的相應(yīng)的 target 元素以及依賴。
  • 后面每次執(zhí)行的時(shí)候,都判斷目標(biāo)元素或者依賴是否發(fā)生變化,發(fā)生變化,則執(zhí)行對(duì)應(yīng)的 effect 函數(shù)。并更新最后一次執(zhí)行的依賴。
  • 組件卸載的時(shí)候,執(zhí)行 unLoadRef.current?.() 函數(shù),并重置 hasInitRef 為 false。
const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayoutEffect) => {
  /**
   * @param effect
   * @param deps
   * @param target target should compare ref.current vs ref.current, dom vs dom, ()=>dom vs ()=>dom
   */
  const useEffectWithTarget = (
    effect: EffectCallback,
    deps: DependencyList,
    target: BasicTarget<any> | BasicTarget<any>[],
  ) => {
    const hasInitRef = useRef(false);

    const lastElementRef = useRef<(Element | null)[]>([]);
    const lastDepsRef = useRef<DependencyList>([]);

    const unLoadRef = useRef<any>();

    // useEffect 或者 useLayoutEffect
    useEffectType(() => {
      // 處理 DOM 目標(biāo)元素
      const targets = Array.isArray(target) ? target : [target];
      const els = targets.map((item) => getTargetElement(item));

      // init run
      // 首次初始化的時(shí)候執(zhí)行
      if (!hasInitRef.current) {
        hasInitRef.current = true;
        lastElementRef.current = els;
        lastDepsRef.current = deps;
        // 執(zhí)行回調(diào)中的 effect 函數(shù)
        unLoadRef.current = effect();
        return;
      }
      // 非首次執(zhí)行的邏輯
      if (
        // 目標(biāo)元素或者依賴發(fā)生變化
        els.length !== lastElementRef.current.length ||
        !depsAreSame(els, lastElementRef.current) ||
        !depsAreSame(deps, lastDepsRef.current)
      ) {
        // 執(zhí)行上次返回的結(jié)果
        unLoadRef.current?.();

        // 更新
        lastElementRef.current = els;
        lastDepsRef.current = deps;
        unLoadRef.current = effect();
      }
    });
    useUnmount(() => {
      // 卸載
      unLoadRef.current?.();
      // for react-refresh
      hasInitRef.current = false;
    });
  };
  return useEffectWithTarget;
};

思考與總結(jié)

一個(gè)優(yōu)秀的工具庫(kù)應(yīng)該有自己的一套輸入輸出規(guī)范,一來(lái)能夠支持更多的場(chǎng)景,二來(lái)可以更好的在內(nèi)部進(jìn)行封裝處理,三來(lái)使用者能夠更加快速熟悉和使用相應(yīng)的功能,能做到舉一反三。

到此這篇關(guān)于JavaScript中ahooks 處理 DOM 的方法的文章就介紹到這了,更多相關(guān)ahooks 處理 DOM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Ionic實(shí)現(xiàn)頁(yè)面下拉刷新(ion-refresher)功能代碼

    Ionic實(shí)現(xiàn)頁(yè)面下拉刷新(ion-refresher)功能代碼

    這篇文章主要介紹了使用Ionic實(shí)現(xiàn)頁(yè)面下拉刷新(ion-refresher)功能的代碼,感興趣的朋友一起看看吧
    2016-06-06
  • 小程序?qū)崿F(xiàn)長(zhǎng)按保存圖片的方法

    小程序?qū)崿F(xiàn)長(zhǎng)按保存圖片的方法

    這篇文章主要介紹了小程序?qū)崿F(xiàn)長(zhǎng)按保存圖片的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 純JS實(shí)現(xiàn)監(jiān)控本地文件變化

    純JS實(shí)現(xiàn)監(jiān)控本地文件變化

    你是否曾夢(mèng)想擁有一個(gè)能夠?qū)崟r(shí)監(jiān)控本地文件變化的網(wǎng)頁(yè)應(yīng)用,現(xiàn)在,這個(gè)夢(mèng)想即將成為現(xiàn)實(shí),本文將通過(guò)純JS實(shí)現(xiàn)這一功能,感興趣的小伙伴可以了解下
    2025-04-04
  • js獲取判斷上傳文件后綴名的示例代碼

    js獲取判斷上傳文件后綴名的示例代碼

    本篇文章主要是對(duì)js獲取判斷上傳文件后綴名的示例代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2014-02-02
  • javascript 添加和移除函數(shù)的通用方法

    javascript 添加和移除函數(shù)的通用方法

    javascript 添加和移除函數(shù)的通用方法, 需要的朋友可以參考下。
    2009-10-10
  • JS異步的執(zhí)行原理和回調(diào)詳解

    JS異步的執(zhí)行原理和回調(diào)詳解

    這篇文章主要給大家介紹了關(guān)于JS異步的執(zhí)行原理和回調(diào)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 微信小程序使用template標(biāo)簽實(shí)現(xiàn)五星評(píng)分功能

    微信小程序使用template標(biāo)簽實(shí)現(xiàn)五星評(píng)分功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序使用template標(biāo)簽實(shí)現(xiàn)五星評(píng)分功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • DIV+CSS+JS 變灰彈出層

    DIV+CSS+JS 變灰彈出層

    javascript 彈出層效果代碼。需要的朋友可以測(cè)試下。
    2009-10-10
  • JavaScript中btoa和atob全局函數(shù)示例詳解

    JavaScript中btoa和atob全局函數(shù)示例詳解

    這篇文章主要給大家介紹了關(guān)于JavaScript中btoa和atob全局函數(shù)的相關(guān)資料,atob和btoa是window對(duì)象的兩個(gè)函數(shù),用來(lái)編碼解碼Base64,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • JS實(shí)現(xiàn)canvas簡(jiǎn)單小畫(huà)板功能

    JS實(shí)現(xiàn)canvas簡(jiǎn)單小畫(huà)板功能

    這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)canvas簡(jiǎn)單小畫(huà)板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06

最新評(píng)論

奎屯市| 化州市| 景德镇市| 泗洪县| 上林县| 阿拉善右旗| 桐梓县| 石嘴山市| 凌源市| 庐江县| 莆田市| 宝丰县| 繁昌县| 桦甸市| 谢通门县| 志丹县| 三亚市| 吉隆县| 内江市| 长兴县| 满城县| 罗平县| 禹城市| 呼玛县| 绥阳县| 勃利县| 封开县| 锡林浩特市| 桦南县| 康定县| 大庆市| 民县| 札达县| 徐州市| 婺源县| 玉溪市| 马公市| 德惠市| 枞阳县| 潜江市| 牙克石市|