日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

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

瀏覽:218日期:2022-06-02 08:58:07
目錄
  • 背景
  • 實現
  • 結語

背景

現在手機應用經常有這樣一個場景:

頁面上有一個導航,導航位置在頁面中間位置,當頁面頂部滾動到導航位置時,導航自動吸頂,頁面繼續往下滾動時,它就一直在頁面視窗頂部顯示,當往上滾動時,經過最初位置時,導航自動復原,不再吸頂。

效果就如京東超市首頁的導航欄一樣:

下面我們就來具體實現這樣一個 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}    >      <divstyle={{  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 實現具備吸頂和吸底功能組件實例的詳細內容,更多關于React吸頂吸底功能的資料請關注其它相關文章!

標簽: JavaScript
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲精品在线二区| 亚洲一区国产| 日韩不卡一区| 99久久亚洲精品蜜臀| 日韩一区二区三区精品| 伊人久久视频| 日韩av网站在线观看| 日本aⅴ免费视频一区二区三区| 夜夜嗨网站十八久久 | 亚洲女同av| 国产精品一区2区3区| 欧美偷窥清纯综合图区| 欧美专区一区| 你懂的国产精品| 久久精品一区二区三区中文字幕| 国产精品3区| 里番精品3d一二三区| 国产精选久久| 国产一区二区三区国产精品| 国产精品成久久久久| 日韩中文在线播放| 亚洲夜间福利| 久久久久久夜| 午夜久久美女| 99在线精品免费视频九九视| 蜜桃91丨九色丨蝌蚪91桃色| 亚洲精品国模| 日本视频一区二区| 国产精品大片| 91青青国产在线观看精品| 成人羞羞在线观看网站| 91九色精品国产一区二区| 国产亚洲高清视频| 7777精品| 国产白浆在线免费观看| 欧美中文一区二区| 视频一区欧美日韩| 国产精品亚洲综合久久| 91一区二区| 久久久国产精品一区二区中文| 欧美一区三区| 亚洲精品乱码| 久久成人av| 亚洲一区国产一区| 日韩黄色大片网站| 91大神在线观看线路一区| 国产一区二区视频在线看| 国产精品老牛| 日韩一区自拍| 国产精品麻豆成人av电影艾秋 | 亚洲高清久久| 日韩免费av| 欧美一区免费| 性欧美精品高清| 日韩久久电影| 午夜在线精品偷拍| 日本欧美一区| 午夜在线一区| 亚洲神马久久| 日韩国产精品久久久久久亚洲| 日韩精品亚洲专区在线观看| 免费欧美日韩| 亚洲+小说+欧美+激情+另类| 精品国产乱码久久久久久1区2匹| 日韩精品久久久久久久电影99爱| 国产亚洲字幕| 天堂√中文最新版在线| 欧美资源在线| 中文在线免费视频| 欧美一区在线观看视频| 国产日韩精品视频一区二区三区| 国产精品探花在线观看| 成人在线免费观看91| 欧美性感美女一区二区| 亚洲免费福利一区| 精品国产不卡| 夜夜嗨一区二区| 国产精品jk白丝蜜臀av小说| 精品国产亚洲一区二区三区大结局| 四虎884aa成人精品最新| 亚洲综合中文| 精品五月天堂| 羞羞答答国产精品www一本| 国产日韩一区二区三区在线| 欧美日韩在线观看视频小说| 日韩国产一区二| 性感美女一区二区在线观看| 美国欧美日韩国产在线播放| 亚洲日本三级| 国产理论在线| 国产九九精品| 欧美在线网站| 欧美二三四区| 日韩精品高清不卡| 日韩视频一区| 成午夜精品一区二区三区软件| 日本麻豆一区二区三区视频| 亚洲一级网站| 国产传媒在线观看| 91精品国产经典在线观看| 欧美综合二区| 日韩av免费| 精品亚洲a∨一区二区三区18| 午夜在线视频观看日韩17c| 日韩中文欧美| 国产精品一区二区美女视频免费看 | 精品亚洲二区| 成人va天堂| 亚洲不卡av不卡一区二区| 国产精品91一区二区三区| 日韩av不卡在线观看| 高清久久精品| 亚洲精品影院在线观看| 国产专区一区| 国产精品.xx视频.xxtv| 日韩欧美综合| 国产欧美一区二区色老头| 美女在线视频一区| 日精品一区二区三区| 欧美丝袜一区| 热久久久久久| 国产精品a级| 在线一区视频观看| 国产精品中文| 成人日韩精品| 国产欧美一区二区三区精品酒店| 中文另类视频| 久久久国产精品网站| 综合一区在线| 欧美午夜不卡影院在线观看完整版免费| 成人在线视频区| 欧美a级一区二区| 日韩欧美久久| 自拍日韩欧美| 国产99久久久国产精品成人免费| 亚洲涩涩av| 日本午夜大片a在线观看| 在线成人直播| 中文字幕成在线观看| 国产美女亚洲精品7777| 亚洲综合不卡| 精品视频国内| 成人三级高清视频在线看| 欧美久久亚洲| 欧美一区二区三区久久精品| 中文字幕日韩高清在线| 日av在线不卡| 综合激情在线| 亚洲日韩中文字幕一区| 欧美影院三区| 久久久久久久久久久9不雅视频| 国产aa精品| 久久影视一区| 91成人精品| 99国产精品99久久久久久粉嫩| 国产99久久| 午夜欧美精品久久久久久久| re久久精品视频| 国产亚洲永久域名| 久热re这里精品视频在线6| 国产午夜精品一区二区三区欧美| 亚洲国产不卡| 美女国产精品| 羞羞答答国产精品www一本| 一二三区精品| 日韩中文字幕无砖| 国产乱子精品一区二区在线观看 | 久久久久美女| 久久天堂精品| 先锋亚洲精品| 日本电影久久久| 国产精品麻豆成人av电影艾秋| 国产精品丝袜在线播放| 成人午夜网址| 欧美日韩一二三四| 亚洲精品.com| 国产精品久久久久久久免费观看 | 亚洲男人在线| 国产欧美丝祙| 亚洲欧洲日本mm| 日韩福利视频导航| 国产福利片在线观看| 丰满少妇一区| 精品欧美久久| 精品视频久久| 亚洲久久视频| 免费日韩成人| 日韩久久精品网| 一区二区视频欧美| 91久久亚洲| 免费视频一区二区| 欧美伊人影院| 麻豆视频在线观看免费网站黄| 99久久99久久精品国产片果冰 | 欧美日韩一区二区三区四区在线观看 | 日韩av黄色在线| 久久天堂精品| sm久久捆绑调教精品一区| 石原莉奈在线亚洲二区| 美女网站视频一区|