亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

React 實現(xiàn)具備吸頂和吸底功能組件實例

瀏覽:72日期:2022-06-02 08:58:07
目錄
  • 背景
  • 實現(xiàn)
  • 結(jié)語

背景

現(xiàn)在手機應(yīng)用經(jīng)常有這樣一個場景:

頁面上有一個導(dǎo)航,導(dǎo)航位置在頁面中間位置,當頁面頂部滾動到導(dǎo)航位置時,導(dǎo)航自動吸頂,頁面繼續(xù)往下滾動時,它就一直在頁面視窗頂部顯示,當往上滾動時,經(jīng)過最初位置時,導(dǎo)航自動復(fù)原,不再吸頂。

效果就如京東超市首頁的導(dǎo)航欄一樣:

下面我們就來具體實現(xiàn)這樣一個 React 組件,實現(xiàn)后還會再擴展延伸一下 吸底 功能,因為 吸底 場景也不少。

具體要求:

  • 需要可以設(shè)置是 吸頂 還是 吸底
  • 吸頂 可以設(shè)置距離視窗頂部的位置,吸頂 可以設(shè)置距離視窗底部的位置。
  • 可以對正常組件都生效,不影響組件自身的樣式。

實現(xiàn)

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

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

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

下面,我們先實現(xiàn)一個基于 IntersectionObserver 實現(xiàn)的判斷位置的 hook

定義 props 類型:

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

可接受參數(shù):

el: React 的 ref 實例,被判斷判斷位置的 DOM 元素。 options: IntersectionObserver 構(gòu)造函數(shù)的初始化參數(shù)。

具體實現(xiàn):

import React, { useEffect, useState } from "react";export function useIntersection(props: Props): boolean {  const { el, options } = props;  // 是否到了指定位置區(qū)域  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] }    );    // 開始監(jiān)聽    intersectionObserver.observe(el.current);    return (): void => {      // 銷毀      intersectionObserver.disconnect();    };  }, [el.current]);  return intersection;}

現(xiàn)在實現(xiàn)了一個可以根據(jù)傳入的參數(shù)來控制否到了指定位置區(qū)域的 hook :useIntersection

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

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

參數(shù)定義:

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

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

其他自定義參數(shù)說明:

  • top 吸頂距離,元素頂部距離視窗頂部小于等于 top 時,進行吸頂。
  • bottom 吸底部距離,元素底部距離視窗底部大于等于 bottom 時,進行吸底。注意邏輯是和吸頂相反。
  • alwaysFixed,用于支持默認就要一直吸頂或者吸底的情況,需要配合 topbottom 來使用。
  • zIndex 控制吸頂或者吸底時的樣式層級。
  • children children 元素是正常的 React 組件即可。
  • height 被包裹元素的高度.也就是 children 元素 的高度。
  • root,相對視窗的目標元素,也就是可以控制在某個區(qū)域內(nèi)進行吸頂和吸底,但因為這里是用的 fixed 定位,如果需要設(shè)置 root 時,需要改變成 absolute 定位。
  • fixedClassName 吸頂和吸底的時候需要動態(tài)添加的 className
  • fixedStyle 吸頂和吸底的時候需要動態(tài)添加的 樣式
  • onFixedChange 吸頂和吸底的時候告訴外界。

具體實現(xiàn):

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);  // 設(shè)置監(jiān)聽參數(shù)控制:top 為吸頂距離,bottom 為吸底距離  const options = {    rootMargin: isFiexdTop      ? `-${top || "0px"} 0px 1000000px 0px`      : `0px 0px -${bottom || "0px"} 0px`,    // 設(shè)置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}    >      <divstyle={{  height,  position: shouldFixed ? "fixed" : "initial",  top: isFiexdTop ? top || 0 : undefined,  bottom: isFiexdTop ? undefined : bottom || 0,  zIndex: zIndex,  ...(shouldFixed ? fixedStyle : {}),}}      >{children}      </div>    </div>  );};

實現(xiàn)邏輯:

  • 使用了 alwaysFixed 判斷是否一直懸浮。
  • 默認懸浮頂部,bottom 值存在時,表明要懸浮底部。
  • useIntersection 傳入監(jiān)聽位置控制參數(shù)。
  • 根據(jù) useIntersection 的結(jié)果來判斷是否應(yīng)該 吸頂吸底
  • 做了 style 樣式和 className 傳入處理的問題,以及 zIndex 層級問題。
  • 吸頂時,不進行設(shè)置 bottom,吸底時,不進行設(shè)置 bottom

主要核心邏輯是第 3 點:

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

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

使用方式:

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

實現(xiàn)效果:

可以看出 一直吸頂滾動到設(shè)定位置吸頂一直吸底滾動到設(shè)定位置吸底 四個功能都可以正常工作。

滾動到設(shè)定位置吸底 指的是,從底部向上滾動的時候,這個功能就是為了在劃出屏幕區(qū)域的時候顯示在底部。

大家也可以打開 示例 自己去體驗一下。

結(jié)語

這是之前在比較多的頁面會用到的一個功能點,然后寫了幾次后,發(fā)現(xiàn)每次實現(xiàn)這個功能都有點復(fù)雜,于是封裝了 吸頂 組件,本次寫文章,就想著剛好可以完善一下,把 吸底 功能也開發(fā)出來,因為后續(xù)也有用到過不少次。

以上就是React 實現(xiàn)具備吸頂和吸底功能組件實例的詳細內(nèi)容,更多關(guān)于React吸頂吸底功能的資料請關(guān)注其它相關(guān)文章!

標簽: JavaScript
主站蜘蛛池模板: 欧美成人亚洲国产精品 | 五月天婷婷精品视频 | 777国产精品永久免费观看 | 不卡黄色| 最新91网址| 亚洲视频91| 成人淫片免费视频95视频 | 日韩版码免费福利视频 | 色视频亚洲 | 成人久久精品 | 成人午夜在线观看国产 | 成人亚洲欧美日韩在线观看 | 免费一级a毛片在线播 | 国产午夜视频在永久在线观看 | 国产高清在线精品一区免费97 | 亚洲国产成人手机在线电影bd | 亚洲人成一区二区三区 | 日本美女视频韩国视频网站免费 | 精品自在线 | 千百橹最新亚洲地址在线播放 | 亚洲欧美色图 | 三级黄色在线视频 | 久久国产免费观看精品 | 天天天天鲁天天拍一拍 | 看一级毛片免费观看视频 | 91在线视频免费看 | 免费碰碰视频 | 亚州一区| 色草在线 | 亚洲夜色 | 精品在线一区二区三区 | 日韩高清免费在线观看 | 国内自拍视频在线观看 | 亚色综合 | 成人欧美一区二区三区黑人免费 | 免费播放成人生活片 | 国产精品人体私拍99pans | 青草伊伊 | 国产黄色片在线免费观看 | 国产亚洲视频在线观看 | 免费亚洲成人 |