91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React如何實現具備吸頂和吸底功能組件

發布時間:2023-02-23 13:56:44 來源:億速云 閱讀:143 作者:iii 欄目:開發技術

本篇內容介紹了“React如何實現具備吸頂和吸底功能組件”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

具體要求:

  • 需要可以設置是 吸頂 還是 吸底

  • 吸頂 可以設置距離視窗頂部的位置,吸頂 可以設置距離視窗底部的位置。

  • 可以對正常組件都生效,不影響組件自身的樣式。

實現

組件主要是為了 吸頂 或者 吸底 功能,那么就命名為 AutoFixed

主要實現邏輯:需要判斷自身在視窗內的位置與設置的 吸頂 或者 吸底 位置是否匹配,匹配上了則可以進行 吸頂 或者 吸底

獲取自身位置一般可以用 滾動的位置自身距離頁面頂部 的位置來判斷,但實現起來會麻煩一些,IntersectionObserver也很好用,而且性能會更好,因此這里將直接使用 IntersectionObserver 來處理。

下面,我們先實現一個基于 IntersectionObserver 實現的判斷位置的 hook

定義 props 類型:

import { RefObject } from "react";
type Props = {
  el: React.RefObject<Element>;
  options?: IntersectionObserverInit;
};

可接受參數:

el: React 的 ref 實例,被判斷判斷位置的 DOM 元素。 options: IntersectionObserver 構造函數的初始化參數。

具體實現:

import React, { useEffect, useState } from "react";
export function useIntersection(props: Props): boolean {
  const { el, options } = props;
  // 是否到了指定位置區域
  const [intersection, setIntersection] = useState(true);
  useEffect(() => {
    if (!el.current) return;
    // 初始化 IntersectionObserver 實例
    const intersectionObserver = new IntersectionObserver(
      function (entries) {
        setIntersection(entries[0].intersectionRatio === 1);
      },
      { ...options, threshold: [1] }
    );
    // 開始監聽
    intersectionObserver.observe(el.current);
    return (): void => {
      // 銷毀
      intersectionObserver.disconnect();
    };
  }, [el.current]);
  return intersection;
}

現在實現了一個可以根據傳入的參數來控制否到了指定位置區域的 hook :useIntersection

useIntersection 只是對 IntersectionObserver 的簡單封裝,并沒有復雜實現,具體作用就是用于判斷某個元素是否進入了 可視窗口,想了解更多可以點擊去查看它的MDN文檔。

下面再來實現我們要實現的具備吸頂和吸底功能的組件:AutoFixed

參數定義:

export type AutoFixedProps = React.ImgHTMLAttributes<HTMLDivElement> & {
  /** 吸頂距離 */
  top?: string;
  /** 吸底距離 */
  bottom?: string;
  /** 是否一直吸頂或者吸底 */
  alwaysFixed?: boolean;
  zIndex?: number;
  children: React.ReactNode;
  /** 元素框高度 */
  height: number | string;
  /** 相對的目標元素,因為是用的 fixed 定位,記得做相應處理。 */
  root?: Element | Document | null;
  /** 固定的時候才有的className */
  fixedClassName?: string;
  /** 固定的時候才有的樣式 */
  fixedStyle?: React.CSSProperties;
  /** fixed狀態改變時調用 */
  onFixedChange?: (isFixed: boolean) => void;
};

可接受參數 基于 React.HtmlHTMLAttributes<HTMLDivElement> ,也就是繼承了 div 的默認屬性。

其他自定義參數說明:

  • top 吸頂距離,元素頂部距離視窗頂部小于等于 top 時,進行吸頂。

  • bottom 吸底部距離,元素底部距離視窗底部大于等于 bottom 時,進行吸底。注意邏輯是和吸頂相反。

  • alwaysFixed,用于支持默認就要一直吸頂或者吸底的情況,需要配合 topbottom 來使用。

  • zIndex 控制吸頂或者吸底時的樣式層級。

  • children children 元素是正常的 React 組件即可。

  • height 被包裹元素的高度.也就是 children 元素 的高度。

  • root,相對視窗的目標元素,也就是可以控制在某個區域內進行吸頂和吸底,但因為這里是用的 fixed 定位,如果需要設置 root 時,需要改變成 absolute 定位。

  • fixedClassName 吸頂和吸底的時候需要動態添加的 className

  • fixedStyle 吸頂和吸底的時候需要動態添加的 樣式

  • onFixedChange 吸頂和吸底的時候告訴外界。

具體實現:

import React, { useRef, useEffect } from "react";
import { useIntersection } from "../../components/hooks/use-intersection";
export const AutoFixed = (props: AutoFixedProps) => {
  const {
    alwaysFixed,
    top,
    bottom,
    style,
    height,
    root,
    zIndex = 100,
    children,
    className,
    fixedClassName,
    fixedStyle,
    onFixedChange,
    ...rest
  } = props;
  // `bottom` 值存在時,表面要懸浮底部
  const isFiexdTop = !bottom;
  const wrapperRef = useRef<HTMLDivElement>(null);
  // 設置監聽參數控制:top 為吸頂距離,bottom 為吸底距離
  const options = {
    rootMargin: isFiexdTop
      ? `-${top || "0px"} 0px 1000000px 0px`
      : `0px 0px -${bottom || "0px"} 0px`,
    // 設置root
    root,
  } as IntersectionObserverInit;
  // 是否懸浮
  const intersection = useIntersection({ el: wrapperRef, options });
  const shouldFixed = alwaysFixed ? true : !intersection;
  useEffect(() => {
    // 通知外部
    onFixedChange?.(shouldFixed);
  }, [shouldFixed, onFixedChange]);
  return (
    <div
      style={{ ...style, height }}
      {...rest}
      className={`${className}${shouldFixed ? " fixedClassName" : ""}`}
      ref={wrapperRef}
    >
      <div
        style={{
          height,
          position: shouldFixed ? "fixed" : "initial",
          top: isFiexdTop ? top || 0 : undefined,
          bottom: isFiexdTop ? undefined : bottom || 0,
          zIndex: zIndex,
          ...(shouldFixed ? fixedStyle : {}),
        }}
      >
        {children}
      </div>
    </div>
  );
};

實現邏輯:

  • 使用了 alwaysFixed 判斷是否一直懸浮。

  • 默認懸浮頂部,bottom 值存在時,表明要懸浮底部。

  • useIntersection 傳入監聽位置控制參數。

  • 根據 useIntersection 的結果來判斷是否應該 吸頂吸底

  • 做了 style 樣式和 className 傳入處理的問題,以及 zIndex 層級問題。

  • 吸頂時,不進行設置 bottom,吸底時,不進行設置 bottom

主要核心邏輯是第 3 點:

const options = {
    rootMargin: `-${top || "0px"} 0px -${bottom || "0px"} 0px`,
};

rootMargin 中:-${top || "0px"} 為吸頂距離,-${bottom || "0px"} 為吸底距離。一定要是負的,正數表示延伸到了視窗外的距離,負數表示距離視窗頂部或者底部的距離。

使用方式:

<AutoFixed
    // 距離頂部為 20px 吸頂
    top="20px"
    // 占位高度,也就是 children 的高度
    height="20px"
    // fixed狀態改變時
    onFixedChange={(isFixed) => {
      console.log(`isFixed: ` + isFixed);
    }}
    // fixed狀態需要添加的className
    fixedClassName="hello"
    // fixed狀態需要添加的style
    fixedStyle={{ color: "red" }}
>
    <div>
        我是懸浮內容,高度 20px, 距離頂部為 20px 吸頂
    </div>
</AutoFixed>

“React如何實現具備吸頂和吸底功能組件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

赤峰市| 慈溪市| 酉阳| 安义县| 黑水县| 苏尼特右旗| 新乡县| 靖西县| 新宁县| 鄯善县| 金塔县| 桓台县| 溧阳市| 卓资县| 教育| 洞口县| 清水河县| 江达县| 东光县| 旬阳县| 安吉县| 驻马店市| 寿阳县| 合作市| 敦化市| 灵寿县| 密山市| 肥西县| 三明市| 遂昌县| 溧水县| 南安市| 温州市| 大同县| 财经| 河北省| 丰原市| 金川县| 威海市| 鸡西市| 增城市|