简体   繁体   English

移动设备上的 Safari 浏览器后退按钮,不会将用户返回到上一页的最后滚动位置

[英]Safari browser back button on mobile, doesn't return user to last scroll position on previous page

I am trying to make my webpage return the user to their last scroll position of the previous page when they click the browser back button.我试图让我的网页在用户单击浏览器后退按钮时将用户返回到上一页的最后滚动位置。

What Should Happen:应该发生什么:

The user clicks a link on the page which directs them to a different site, then when they click the browser back button they should return to the previous page at the last scroll position.用户单击页面上的链接,将他们定向到不同的站点,然后当他们单击浏览器后退按钮时,他们应该返回到最后滚动位置的上一页。 This works correctly on Chrome and Safari on macOS automatically with no code needed.这在 macOS 上的 Chrome 和 Safari 上自动正常工作,无需代码。

Problem:问题:

When testing on Safari on an iPhone, the user is always returned to the top of the webpage, not their last scroll position.在 iPhone 上的 Safari 上进行测试时,用户总是返回到网页的顶部,而不是他们最后的滚动位置。

Are there any know reasons as to why Safari on mobile returns to the top of the previous page when the browser back button is clicked?单击浏览器后退按钮时,移动设备上的 Safari 为何返回上一页顶部,是否有任何已知原因?

Code : The below code attempts to save the last scroll position in localStorage and then scroll to that position when popState is triggered.代码:下面的代码尝试将最后一个滚动位置保存在 localStorage 中,然后在 popState 被触发时滚动到该位置。 PopState is used because other triggers like load seem to not work when the back button is clicked on Safari.使用 PopState 是因为在 Safari 上单击后退按钮时,其他触发器(如 load)似乎不起作用。 With these considerations it still does not work.考虑到这些,它仍然不起作用。

I'm not sure if maybe popstate is fired differently on mobile or maybe localStorage isn't saved when the webpage is exited.我不确定 popstate 在移动设备上是否以不同的方式触发,或者在退出网页时 localStorage 是否未保存。

$(window).on('popstate', function(event) {

    var is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    if(is_safari){
    if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
    }
     var scroll = window.localStorage.getItem('scroll');
     if (scroll !== null) $(document).scrollTop( scroll );

    }
 });


$(window).on('scroll', function() {
    window.localStorage.setItem("scroll", $(document).scrollTop());
 });


I was able to find a temporary solution but I still think it could be improved upon.我能够找到一个临时解决方案,但我仍然认为它可以改进。

Explanation:解释:

Using a recursive function and local storage, I was able to keep track of and constantly update the scroll position.使用递归函数和本地存储,我能够跟踪并不断更新滚动位置。 When an external link is clicked, the scroll position is saved and a 'flag variable' is set to 0 in local storage.当点击外部链接时,滚动位置被保存,并且在本地存储中将“标志变量”设置为 0。

When the user returns via the browser back button, the recursive function begins to constantly update the scroll position to the variable saved in local storage.当用户通过浏览器返回按钮返回时,递归函数开始不断将滚动位置更新为保存在本地存储中的变量。 Then once the user drags the screen the 'flag-variable' is changed to 1 and the function stops updating the scroll position so the user can drag freely.然后,一旦用户拖动屏幕,'flag-variable' 将更改为 1,并且该函数停止更新滚动位置,以便用户可以自由拖动。

Code:代码:

// check if browser is Safari
window.is_safari = true;
$(document).ready(function(){
  window.is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
});

// when external link is clicked store scroll position and flag to localStorage
$('.external-link').on('click', function() {

    // save scroll position to local storage
    window.localStorage.setItem("scroll", $(document).scrollTop());

    // check the size of window (most likely on touch screen if below this size)
    if($(window).width() <= 1000)
    {

    // save flag variable to local storage
    window.localStorage.setItem("returnPos", 0);
    }
 });


 function repeatFunction(){

    if(window.localStorage.getItem('returnPos') == 0)
    {
        // keep the scroll position the same as localStorage variable
        $(document).scrollTop( window.localStorage.getItem('scroll') );

        // once user drags change flag to one so this if statement doesn't get entered
        // and scroll position can move freely
        $(document).on('mousedown touchstart', function() 
        {
            window.localStorage.setItem("returnPos", 1); 
        });
    }
    // if Safari keep calling function 
    if(window.is_safari){
    setTimeout(repeatFunction, 100);
    }
}

$(document).ready(function(){
    repeatFunction();
});

Potential Problems:潜在问题:

I assume your website could begin to run slower since this recursive function is being used.我认为您的网站可能会因为使用这个递归函数而开始运行变慢。 Unfortunately, I couldn't get $(window).on('popstate', function(event) {});不幸的是,我无法获得$(window).on('popstate', function(event) {}); to fire on Safari, because of this I'm unsure of how to detect that the page was reloaded through the back button.在 Safari 上触发,因此我不确定如何检测页面是通过后退按钮重新加载的。

Also, if a user is using a touch screen larger than the value checked for in the if statement this method wont work.此外,如果用户使用的触摸屏大于 if 语句中检查的值,则此方法将不起作用。 And if a user is using a desktop with a screen smaller than the value checked for in the if statement they will have to click before being able to scroll upon returning to the page via the Safari browser back button.如果用户使用的桌面屏幕小于 if 语句中检查的值,则他们必须先单击,然后才能通过 Safari 浏览器的后退按钮返回页面进行滚动。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM