您好,登錄后才能下訂單哦!
本篇內容介紹了“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
,用于支持默認就要一直吸頂或者吸底的情況,需要配合 top
和 bottom
來使用。
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如何實現具備吸頂和吸底功能組件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。