【问题标题】:Smooth scroll the ID issue平滑滚动ID问题
【发布时间】:2020-07-17 21:06:09
【问题描述】:

我正在开发一个网站,并且在我的导航栏中有一个“功能”链接。在主页上,如果单击“功能”,我将其向下滚动到带有 id="expo-features" 的 H1(此处简化):

<div class="topnav-right">
      <a href="#expo-features">Features</a>
      <a href="register.php">Registration</a>
      <a href="booth.php">Reserve A Booth</a>
      <a href="sponsor.php">Sponsor Event</a>
      <a href="contact.php">Contact</a>
</div>

/*Scrolls to this section*/

<h1 id="expo-features">Expo Features</h1>

我在头部添加了一些脚本来完成这项工作:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
  // Add smooth scrolling to all links
  $("a").on('click', function(event) {

    // Make sure this.hash has a value before overriding default behavior
    if (this.hash !== "") {
      // Prevent default anchor click behavior
      event.preventDefault();

      // Store hash
      var hash = this.hash;

      // Using jQuery's animate() method to add smooth page scroll
      // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
      $('html, body').animate({
        scrollTop: $(hash).offset().top
      }, 800, function(){

        // Add hash (#) to URL when done scrolling (default click behavior)
        window.location.hash = hash;
      });
    } // End if
  });
});
</script>

一切都很好!它完美地滚动到 expo-features id。当然,由于这是在我的导航中,因此它会出现在其他页面上。所以我需要它能够链接到同一部分(显然它不会滚动到它,因为它会转到不同的页面——但这没关系)。在我的一些页面上,这是有效的。

但是,我有 2 个页面具有自己的唯一 id# 链接,并且头部具有相同的脚本。但是现在位于导航中的“功能”按钮不会跳到那 2 页上。我不知道为什么?


长话短说:here is my website

  • 导航中的“功能”按钮#链接到主页上的部分
  • 适用于主页、注册页面和联系页面
  • “功能”按钮在 booth pagesponsor page 上不起作用,我认为这是因为这些页面有自己独特的 id# 链接,并且头部有相同的脚本。
  • 是的,在其他页面上,“功能”按钮 href="https://virtualdigitalexpo.com/#expo-features"

【问题讨论】:

  • 你知道你可以通过one line of css code做到这一点
  • 如果你检查浏览器的控制台,你会看到这个错误Uncaught TypeError: Cannot read property 'top' of undefined,当你转到错误行时,你会看到它是这个scrollTop: $(hash).offset().top,这意味着$(hash).offset() 未定义,这意味着if (this.hash !== "") 没有像你想象的那样工作,尝试不仅检查"",还要检查null 和@ 之类的东西987654332@ 并尝试查明为什么 this.hash 没有得到正确值的原因

标签: javascript jquery html smooth-scrolling hashtag


【解决方案1】:

这是因为您只检查锚点是否在其href 中设置了hash,而您还需要检查锚点是否实际指向当前文档。

这可以通过构建没有哈希的锚的路径来轻松实现:

// builds an URL path without the hash
function buildPath( url ) {
  return url.origin + url.pathname + url.search;
}

并将其与您的文档进行比较。请注意,您不能使用window.location,因为您的HTML 锚不会将其用作它们的baseURI,而是使用document.baseURI 值,它可以被修改,例如通过&lt;base&gt; 元素。
所以我们需要从那个基础 URI 构建一个新的 URL 实例:

const doc_URI = new URL( document.baseURI );

我们很高兴:

document.onclick = (evt) => {
  const target = evt.target;
  if( target.matches( 'a' ) ) {
    evt.preventDefault();
    const doc_URI = new URL( document.baseURI );
    const is_valid_anchor = target.hash !== "" &&
      buildPath( target ) === buildPath( doc_URI );
    console.log( 'is valid', is_valid_anchor );
  }
};
// builds an URL path without the hash
function buildPath( url ) {
  return url.origin + url.pathname + url.search;
}
a { display: block; }
<a href="#foo">"#foo" (same)</a>
<a href="/some-other-page/#foo">"/some-other-page/#foo" (different)</a>
<a href="?bar=baz#foo">"?bar=baz#foo" (different)</a>
<a href="">"" (different)</a>
<a href="https://stacksnippets.net/js#foo">"https://stacksnippets.net/js#foo" (same)</a>
<a href="http://stacksnippets.net/js#foo">"http://stacksnippets.net/js#foo" (different)</a>

所以在你的代码中会给出

$("a").on('click', function(event) {

  // Make sure this.hash has a value before overriding default behavior
  // And that it points to the current document
  var doc_URI = new URL( document.baseURI );
  if (this.hash !== "" && buildPath( this ) === buildPath( doc_URI )) {
    // the rest of your code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2013-10-01
    相关资源
    最近更新 更多