【问题标题】:jQuery code disabling links to other web pagesjQuery 代码禁用指向其他网页的链接
【发布时间】:2021-07-24 19:02:04
【问题描述】:

我有一些 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>

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

然而,上面的代码不适用于页内链接

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

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

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

$(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 中指定路径而不是仅片段标识符?
  • 该站点使用base 元素,它为所有页面设置了一个固定的初始路径。每个页面都以此为基础。 @Unmitigated

标签: javascript jquery smooth-scrolling


【解决方案1】:

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

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

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>

【讨论】:

    【解决方案2】:

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

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

    语法refer docs

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

    对于2nd的问题

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

    【讨论】:

      猜你喜欢
      • 2012-08-29
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多