React Hooks封装一个简单的锚点固钉的组件

重点

组件封装的过程中遇到一个巨大巨大、比坑爹还坑的坑:开发环境中,此组件能如期输出UI,但在测试环境中部分UI丢失。
某日,在进行codeView的时候,突然发现原来webpack将react的组件名字name给统一压缩成字母t。原来有这样一条属性链
组件实例.type.name == “AnchorPane‘”,如果项目经过build后,则组件实例.type.name == “t”,这样导致filter范围扩大了。
网上有大牛建议在children子组件AnchorPanel中添加 static elementType = 'AnchorPanel’属性
经测试这个属性标识不会被webpack压缩,故能如期输出UI

JS部分

import React, { useState, useEffect, useRef } from 'react';
import { Icon } from 'tinper-bee'
import './index.less'
const AnchorLink = props => {
    if( !props.children ) return null;
    const anchorRef = useRef(null);
    const [isExpanded, setIsExpanded] = useState(true);   //是否展开状态
    const [indx, setIndx] = useState(0); //初始选择的anchor

    // 锚点变更 副函数
    useEffect(() => {
        // 获取当前活动锚点
        const activeAnchor = props.children && props.children.filter(i => i.type && i.type.elementType === 'AnchorPanel').map(i => i.props.anchor)[indx]
        // 计算关联 锚点 到 顶部的距离 
        const topActiveAnchor = anchorRef.current.querySelector(`#${activeAnchor}`);
        topActiveAnchor && anchorRef.current.scrollTo({ top: topActiveAnchor.offsetTop - anchorRef.current.offsetTop, behavior: "smooth" });
    }, [indx])

    return <div className="anchor-link" ref={anchorRef}
        style={{ height: window.innerHeight - (document.querySelector('.anchor-link') ? document.querySelector('.anchor-link').offsetTop+5 : 0), overflowY: 'scroll' }} >
        <ul className="link-postion-fiexd" style={{ ...props.style, width: isExpanded ? '100px' : 'auto' }}>
            <li onClick={() => setIsExpanded(state => !state)}> <Icon type={isExpanded ? 'uf-arrow-right' : 'uf-arrow-left'} />
                {isExpanded && '折叠'}</li>
            {
                props.children && props.children.filter(i => i.type && i.type.elementType === 'AnchorPanel').map((i, index) => {
                    let { anchor, title } = i.props;
                    if( typeof title !== 'string' ){
                        title = `第${index+1}项`;
                        if( props.objText &&  (typeof props.objText[anchor] === 'string') )  title = props.objText[anchor];
                    }
                    return <li className={index === indx ? "anchor-link-item-active" : "anchor-link-item"} key={anchor}
                        onClick={() => setIndx(index)}>
                        {isExpanded &&
                            <span className="anchor-link-text" title={title} > {title.slice(0,5) } </span>
                        }
                    </li>
                })
            }
            <li onClick={() => setIndx(0)}> <Icon type='uf-arrow-up-2' />{isExpanded && '回顶'}</li>
        </ul>
        {props.children}
    </div>
}

export default AnchorLink

CSS部分

.anchor-link {
  .link-postion-fiexd {
    position: fixed;
    background: white;
    top: 10px;
    right: 20px;
    box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
    z-index: 99;
    li {
      cursor: pointer;
      height: 25px;
      line-height: 25px;
      &.anchor-link-item {
        position: relative;
        &::before {
          content: " ";
          display: inline-block;
          width: 6px;
          height: 6px;
          border-radius: 50%;
          background: #b4bbbf;
          position: absolute;
          top: 9px;
          left: 4px;
          margin-right: 10px;
        }
      }

      &.anchor-link-item-active {
        position: relative;
        &::before {
          content: " ";
          display: inline-block;
          width: 10px;
          height: 10px;
          border-radius: 50%;
          background: #0092ff;
          position: absolute;
          top: 9px;
          left: 4px;
          margin-right: 10px;
        }
      }
    }
    .anchor-link-text {
      padding-left: 20px;
    }
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值