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

React實現(xiàn)錨點跳轉(zhuǎn)組件附帶吸頂效果的示例代碼

 更新時間:2023年01月05日 08:52:24   作者:繪繪~  
這篇文章主要為大家詳細介紹了React如何實現(xiàn)移動端錨點跳轉(zhuǎn)組件附帶吸頂效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起了解一下

React實現(xiàn)錨點跳轉(zhuǎn)組件附帶吸頂效果

import React, { useRef, useState, useEffect } from 'react';
import styles from './index.less';
import classnames from 'classnames';

function AnchorTabber(props) {
  const root = useRef(null);
  const header = useRef(null);
  const {
    attrbute = 'data-anchor',
    offsetY = 60,
    list = [],
    initialKey = list[0]?.key,
    children,
  } = props;
  const [state, setState] = useState({
    activeKey: initialKey,
  });
  const [key2Bottom, setKey2Bottom] = useState({
    key2Bottom: {},
  });
  /** @type { HTMLDivElement } */
  const scrollElement = document.querySelector('#root').firstChild;
  function scrollTo(key) {
    // if(!scrollElement) {
    //   scrollElement = document.querySelector('#root').firstChild;
    // }

    const attribute = attrbute;
    /** @type { HTMLDivElement } */
    const targetEl = root.current?.querySelector(`[${attribute}=${key}]`);
    if (targetEl) {
      const clientRect = targetEl.getBoundingClientRect();
      const top = scrollElement.scrollTop + clientRect.top - offsetY;
      scrollElement.scrollTo({
        top,
        behavior: 'smooth',
      });
      // targetEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }

  function updateElementsPosition() {
    const elements = document.querySelectorAll(`[${attrbute}]`);
    Array.from(elements).forEach(element => {
      const targetAttr = element.getAttribute(`${attrbute}`);
      const clientRect = element.getBoundingClientRect();

      const bottom = clientRect.top + scrollElement.scrollTop;
      key2Bottom[targetAttr] = bottom;
    });
    setKey2Bottom(key2Bottom);
  }

  function handleScroll() {
    const top = scrollElement.scrollTop + offsetY;
    // eslint-disable-next-line no-unused-vars
    const target = Object.entries(key2Bottom)
      .sort(([, v1], [, v2]) => v2 - v1)
      .find(([, v]) => v <= top);
    if (target) {
      setState({
        activeKey: target[0],
      });
    }
  }

  useEffect(() => {
    updateElementsPosition();
    // document.addEventListener('touchstart', updateElementsPosition);
    scrollElement.addEventListener('scroll', handleScroll);
    return () => {
      // document.removeEventListener('touchstart', updateElementsPosition);
      scrollElement.removeEventListener('scroll', handleScroll);
    };
  });

  function handleItemClick(tabber) {
    scrollTo(tabber.key);
  }

  function render() {
    let { activeKey } = state;
    if(typeof(activeKey) === "undefined") {
      activeKey = initialKey
    }
    
    return (
      <div className={styles.mAnchorTabber}>
        <div className={styles.header} ref={header}>
          {list?.map(tabber => (
            <div
              className={classnames(styles.item, { [styles.active]: activeKey === tabber.key })}
              onClick={() => handleItemClick(tabber)}
            >
              {tabber.name}
            </div>
          ))}
        </div>
        <div className={styles.container} ref={root}>
          {children}
        </div>
      </div>
    );
  }

  return render();
}


export default AnchorTabber;

對應樣式(less)

.mAnchorTabber {
  .header {
    display: flex;
    align-items: center;
    position: sticky;
    top: 0;
    height: .len(46) [];
    box-sizing: border-box;
    box-shadow: 0 .len(2) [] .len(2) [] .len(1) [] #c4c4c4;
    background-color: @basecolor;
    .item {
      height: 100%;
      flex-grow: 1;
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: 400;
      font-size: @font-size-base-normal;
      line-height: .len(20) [];
      &.active {
        background-color: @bgc-product-detail;
        color: @basecolor;
      }
    }
  }
}

.len(46) []這個改成對應 px單位即可,本單位是為了移動端適配轉(zhuǎn)換

測試test

對應測試文件

import React from 'react';
import { connect } from 'dva';

import AnchorTabber from '@/components/m/AnchorTabber';

@connect(({ common }) => ({
  common,
}))
class ApplicationsRecord extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [
        {
          name: 'test1',
          key: 'test1',
        },
        {
          name: 'test2',
          key: 'test2',
        },
        {
          name: 'test3',
          key: 'test3',
        },
      ],
    };
  }

  render() {
    const { list } = this.state;
    const index2Attr = {
      0: 'test1',
      100: 'test2',
      200: 'test3',
    };
    return (
      <AnchorTabber list={list}>
        <ul className="list">
          {new Array(1000).fill(null).map((_item, index) => (
            <li data-anchor={index2Attr[index]}>{index}</li>
          ))}
        </ul>
      </AnchorTabber>
    );
  }
}
export default ApplicationsRecord;

到此這篇關于React實現(xiàn)錨點跳轉(zhuǎn)組件附帶吸頂效果的示例代碼的文章就介紹到這了,更多相關React錨點跳轉(zhuǎn)組件附帶吸頂效果內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 關于React狀態(tài)管理的三個規(guī)則總結(jié)

    關于React狀態(tài)管理的三個規(guī)則總結(jié)

    隨著 JavaScript 單頁應用開發(fā)日趨復雜,JavaScript 需要管理比任何時候都要多的 state (狀態(tài)),這篇文章主要給大家介紹了關于React狀態(tài)管理的三個規(guī)則,需要的朋友可以參考下
    2021-07-07
  • React中路由的參數(shù)傳遞路由的配置文件詳解

    React中路由的參數(shù)傳遞路由的配置文件詳解

    路由的配置文件目前我們所有的路由定義都是直接使用Route組件,并且添加屬性來完成的,路由的參數(shù)傳遞有二種方式這,兩種方式在Router6.x中都是提供的hook函數(shù)的API,?類組件需要通過高階組件的方式使用,本文通過示例代碼詳解講解,需要的朋友參考下吧
    2022-11-11
  • react數(shù)據(jù)管理機制React.Context源碼解析

    react數(shù)據(jù)管理機制React.Context源碼解析

    這篇文章主要為大家介紹了react數(shù)據(jù)管理機制React.Context源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • React 路由傳參的幾種實現(xiàn)方法

    React 路由傳參的幾種實現(xiàn)方法

    React中傳參方式有很多,通過路由傳參的方式也是必不可少的一種,本文主要介紹了React路由傳參的幾種實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • React中的路由嵌套和手動實現(xiàn)路由跳轉(zhuǎn)的方式詳解

    React中的路由嵌套和手動實現(xiàn)路由跳轉(zhuǎn)的方式詳解

    這篇文章主要介紹了React中的路由嵌套和手動實現(xiàn)路由跳轉(zhuǎn)的方式,手動路由的跳轉(zhuǎn),主要是通過Link或者NavLink進行跳轉(zhuǎn)的,實際上我們也可以通JavaScript代碼進行跳轉(zhuǎn),需要的朋友可以參考下
    2022-11-11
  • React項目中動態(tài)插入HTML內(nèi)容的實現(xiàn)

    React項目中動態(tài)插入HTML內(nèi)容的實現(xiàn)

    本文主要介紹了React項目中動態(tài)插入HTML內(nèi)容的實現(xiàn),通過使用React的dangerouslySetInnerHTML屬性,我們可以將HTML內(nèi)容插入到組件中,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • React常見跨窗口通信方式實例詳解

    React常見跨窗口通信方式實例詳解

    這篇文章主要為大家介紹了React常見跨窗口通信方式實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React?性能優(yōu)化方法總結(jié)

    React?性能優(yōu)化方法總結(jié)

    這篇文章主要介紹了React性能優(yōu)化方法總結(jié),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • Rect Intersection判斷兩個矩形是否相交

    Rect Intersection判斷兩個矩形是否相交

    這篇文章主要為大家介紹了Rect Intersection判斷兩個矩形是否相交的算法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • 淺談React 的引入

    淺談React 的引入

    React相比于Vue,更注重對JS的掌握,Vue把能做的都做了,只剩下最簡單的讓開發(fā)者使用,開發(fā)者需要記憶Vue的特定指令后就可很輕松地開發(fā)。相反,React是提供了一種思路和方式,沒有過多的限制,但要求會相對高些,需要開發(fā)者對JS達到精通的地步才能真正運用好React。
    2021-05-05

最新評論

内江市| 志丹县| 朝阳区| 山西省| 洛扎县| 大关县| 九龙县| 镶黄旗| 双峰县| 东辽县| 天门市| 得荣县| 焉耆| 宿迁市| 伽师县| 奈曼旗| 公安县| 南澳县| 惠东县| 望奎县| 涿鹿县| 镇宁| 山西省| 陵水| 迁安市| 车致| 米易县| 商洛市| 什邡市| 建阳市| 讷河市| 襄城县| 赤峰市| 叶城县| 岗巴县| 中宁县| 濮阳县| 佛教| 盐亭县| 新巴尔虎左旗| 六安市|