有没有办法在页面加载时覆盖浏览器的默认滚动到散列行为? [英] Is there a way to override the browser’s default scroll to hash behavior on page load?

查看:27
本文介绍了有没有办法在页面加载时覆盖浏览器的默认滚动到散列行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个固定定位的标题,当用户向下滚动时,它会向上滑动以隐藏"类似于 Medium 上的标题(例如:https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a).

I have a fixed positioned header that "slides up to hide" when users scroll down similar to the one on Medium (example: https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a).

问题出在 iOS 上,当浏览器在页面加载时滚动到散列时(例如,#368a 在 Medium),一些内容(如何获得您自己的虚荣洋葱地址? 例如在 Medium 上)出现在标题下.

Problem is on iOS, when the browser scrolls to hash on page load (#368a on Medium for example), some content (How to get your very own vanity onion address? on Medium for example) appears under the header.

我希望处理(覆盖)默认滚动到散列逻辑(类似于 event.preventDefault() 之类的东西)以更好地控制滚动的位置,考虑到标题等.

I wish to handle (override) the default scroll to hash logic (something to the likes of event.preventDefault()) to have more control on where to scroll, accounting for the height of the header among other things.

我能够使用以下逻辑在 React 上处理页内导航.

I am able to handle in-page navigation on React using the following logic.

const scrollWithOffset = (element: HTMLElement, offset:number) => {
  let offsetTop = element.getBoundingClientRect().top;
  const elementPosition = offsetTop - offset - 20;
  window.scroll({
    top: elementPosition,
    left: 0,
    behavior: 'smooth'
  });
};

<HashLink
  to={props.href}
  scroll={el => scrollWithOffset(el, 104)}
  smooth
>{props.children}</HashLink>

希望将相同的逻辑应用于页面加载时的默认滚动到散列行为.

Would love to apply the same logic to the default scroll to hash behavior on page load.

推荐答案

感谢@TJCrowder 的宝贵反馈和 这个问题,我能够组合一个 React 组件,该组件覆盖页面加载时浏览器的默认滚动到散列行为.

Thanks to the precious feedback of @T.J.Crowder and to this question, I was able to put together a React component that overrides the browser’s default scroll to hash behavior on page load.

这个组件的行为受到 Medium 的启发.页面最初加载时不会滚动到元素,经过短暂的延迟(一旦所有内容都有时间加载),它就会启动滚动.请参阅 https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a.我喜欢这种延迟如何帮助将滚动上下文化.

The behavior of this component is inspired by Medium. The page initially loads without scrolling to the element and, after a short delay (once everything has had time to load), it initiates the scroll. See https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a. I like how this delay helps contextualize the scroll.

秘诀是快速交换散列所指元素的 id(禁用默认滚动到散列)并恢复到真正的 id 一旦 DOM 有时间加载.

The secret sauce is to quickly swap the id of the element to which the hash refers to (which disables the default scroll to hash) and to revert back to the real id once the DOM has had time to load.

export const scrollToWithOffset = (element: HTMLElement, offset:number, smooth?: boolean) => {
  let offsetTop = element.getBoundingClientRect().top + window.pageYOffset;
  let maxScrollTop = document.body.scrollHeight - document.body.clientHeight;
  let options: ScrollToOptions = {
    top: Math.min(offsetTop - offset, maxScrollTop),
    left: 0,
  };
  if (smooth === true) {
    options.behavior = 'smooth';
  }
  window.scroll(options);
};

interface ScrollToHashProps {}

interface ScrollToHashState {
  element?: HTMLElement;
}

export class ScrollToHash extends Component<ScrollToHashProps, ScrollToHashState> {
  constructor(props: ScrollToHashProps) {
    super(props);
    this.handleScroll = this.handleScroll.bind(this);
  }
  handleScroll() {
    setTimeout(() => {
      if (this.state.element) {
        this.state.element.id = this.state.element.id.replace('-sth', '');
        setTimeout(() => {
          if (this.state.element) {
            scrollToWithOffset(this.state.element, 0);
          }
        }, 1000);
      }
    }, 0);
  }
  componentDidMount() {
    if (window.location.hash !== '') {
      let element = document.getElementById(window.location.hash.replace('#', ''));
      if (element) {
        element.id += '-sth';
        this.setState({
          element: element
        });
        if (document.readyState === 'loading') {
          window.addEventListener('DOMContentLoaded', this.handleScroll);
        } else {
          this.handleScroll();
        }
      }
    }
  }
  componentWillUnmount() {
    window.removeEventListener('DOMContentLoaded', this.handleScroll);
  }
  render() {
    return null;
  }
}

这篇关于有没有办法在页面加载时覆盖浏览器的默认滚动到散列行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆