jQuery 禁用指向其他网页的链接的代码

jQuery code disabling links to other web pages

我有一些 jQuery 代码可以在我的网页上平滑滚动。

$(document).ready(function(){
    // browser window scroll position (in pixels) where the button will appear
    var offset = 200,
        
    // duration of the animation (in ms)
    scroll_top_duration = 700,
    
    // bind with the button
    $back_to_top = $('.back-to-top');

    // display and hide the button
    $(window).scroll(function(){
        ( $(this).scrollTop() > offset ) ? $back_to_top.addClass('make-visible-btt') : $back_to_top.removeClass('make-visible-btt');
    });

    //smooth scroll to top
    $back_to_top.on('click', function(event){
        event.preventDefault();
        $('body,html').animate({
            scrollTop: 0 ,
            }, scroll_top_duration
        );
    });
});

$(document).ready(function() {
  // browser window scroll position (in pixels) where the button will appear
  var offset = 200,

    // duration of the animation (in ms)
    scroll_top_duration = 700,

    // bind with the button
    $back_to_top = $('.back-to-top');

  // display and hide the button
  $(window).scroll(function() {
    ($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
  });

  //smooth scroll to top
  $back_to_top.on('click', function(event) {
    event.preventDefault();
    $('body,html').animate({
      scrollTop: 0,
    }, scroll_top_duration);
  });
});
.back-to-top {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: inline-block;
  height: 40px;
  width: 40px;
  background: url(../images/back-to-top.png) no-repeat;
  background-size: contain;
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
  border: 1px solid #aaa;
  visibility: hidden;
  opacity: 0;
  transition: opacity .3s 0s, visibility 0s .3s;
}

.make-visible-btt {
  visibility: visible;
  opacity: 1;
  transition: opacity 1s 0s, visibility 0s 0s;
}

.section {
  border: 1px solid black;
  background-color: #ededed;
  height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#last">jump to last section</a>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
<a href="/my-web-page/" class="back-to-top">Back to Top</a>

代码运行良好。当用户点击页面上的“回到顶部”按钮时,他们会自动平滑滚动到顶部。一切顺利。

但是,上面的代码 不适用于页内 links

<a href="/my-web-page/#section-3">text text text</a>

因此,如果用户像上面那样单击 link,页面会立即跳转到该部分(这是默认行为)。

我添加了这段代码来解决这个问题:

$(document).ready(function(){
  $('a[href*="\#"]').on('click', function(event){
    var href = $(event.target).closest('a').attr('href'), 
        skip = false;
    if (!skip) {
      event.preventDefault();
      $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
    }
  });
});

$(document).ready(function() {
  // browser window scroll position (in pixels) where the button will appear
  var offset = 200,

    // duration of the animation (in ms)
    scroll_top_duration = 700,

    // bind with the button
    $back_to_top = $('.back-to-top');

  // display and hide the button
  $(window).scroll(function() {
    ($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
  });

  //smooth scroll to top
  $back_to_top.on('click', function(event) {
    event.preventDefault();
    $('body,html').animate({
      scrollTop: 0,
    }, scroll_top_duration);
  });
});
$(document).ready(function(){
  $('a[href*="\#"]').on('click', function(event){
    var href = $(event.target).closest('a').attr('href'), 
        skip = false;
    if (!skip) {
      event.preventDefault();
      $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
    }
  });
});
.back-to-top {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: inline-block;
  height: 40px;
  width: 40px;
  background: url(../images/back-to-top.png) no-repeat;
  background-size: contain;
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
  border: 1px solid #aaa;
  visibility: hidden;
  opacity: 0;
  transition: opacity .3s 0s, visibility 0s .3s;
}

.make-visible-btt {
  visibility: visible;
  opacity: 1;
  transition: opacity 1s 0s, visibility 0s 0s;
}

.section {
  border: 1px solid black;
  background-color: #ededed;
  height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#last">jump to last section</a>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
<a href="/my-web-page/" class="back-to-top">Back to Top</a>

现在已经解决了。

但是第二个代码块产生了两个新问题:

  1. 带有片段标识符(例如 #section-of-page)的链接不再在浏览器地址栏中更新。例如,在一个页面中,单击时,页面确实会平滑地滚动到目标部分(因此可以正常工作),但网址保持固定在 www.website.com/whatever,而它应该更新为 www.website.com/whatever#section-of-page

  2. 带有片段标识符的链接不能跨页面工作。换句话说,/this-web-page#section-of-page 工作正常。但是 /another-web-page#section-of-pagewww.another-website.com/whatever#section-of-page 都失败了(点击什么都不做)。

在添加第二个代码块之前不存在这些问题。

正在寻找有关如何解决这些问题的指导。

此外,如果您能提出一种将所有功能集成到一个代码块中的方法,那就太好了。

最后,我知道 CSS scroll-behavior 属性,但它仍然很初级(无法调整任何设置),所以我宁愿坚持使用 JS现在。

谢谢。

您可以检查 href 是否指向内部位置,方法是从它创建一个 URL 对象并检查其 hostwindow.location.host。然后调用 event.preventDefault 并仅在这种情况下执行平滑滚动。

$.animate的回调函数(第三个参数)可用于在滚动效果后正确设置散列。

if (new URL(href, window.location).host === window.location.host) {
    event.preventDefault();
    $('html,body').animate({
        scrollTop: $(this.hash).offset().top
    }, 500, function() {
        window.location.hash = new URL(href, window.location).hash;
    });
}

$(document).ready(function() {
  // browser window scroll position (in pixels) where the button will appear
  var offset = 200,

    // duration of the animation (in ms)
    scroll_top_duration = 700,

    // bind with the button
    $back_to_top = $('.back-to-top');

  // display and hide the button
  $(window).scroll(function() {
    ($(this).scrollTop() > offset) ? $back_to_top.addClass('make-visible-btt'): $back_to_top.removeClass('make-visible-btt');
  });

  //smooth scroll to top
  $back_to_top.on('click', function(event) {
    event.preventDefault();
    $('body,html').animate({
      scrollTop: 0,
    }, scroll_top_duration);
  });
});
$(document).ready(function(){
  $('a[href*="\#"]').on('click', function(event){
    var href = $(event.target).closest('a').attr('href');
    if (new URL(href, window.location).host === window.location.host) {
        event.preventDefault();
        $('html,body').animate({
            scrollTop: $(this.hash).offset().top
        }, 500, function() {
            window.location.hash = new URL(href, window.location).hash;
        });
    }
  });
});
.back-to-top {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: inline-block;
  height: 40px;
  width: 40px;
  background: url(../images/back-to-top.png) no-repeat;
  background-size: contain;
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
  border: 1px solid #aaa;
  visibility: hidden;
  opacity: 0;
  transition: opacity .3s 0s, visibility 0s .3s;
}

.make-visible-btt {
  visibility: visible;
  opacity: 1;
  transition: opacity 1s 0s, visibility 0s 0s;
}

.section {
  border: 1px solid black;
  background-color: #ededed;
  height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#last">jump to last section</a>
<a href="https://example.com">External link</a>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section" id="last"></div>
<a href="/my-web-page/" class="back-to-top">Back to Top</a>

for 1st 问题是因为 event.preventDefault();。如果您删除此行,则浏览器 url 将相应更新。

如果您发现任何问题,请在动画完成/结束后再次尝试设置 url。

语法 refer docs

$('html,body').animate({
        scrollTop: $(href).offset().top
    }, 500, function () {
        window.location.hash = href;
    });

对于2nd个问题

通过放置调试点检查回调是否命中点击