刷新页面并保持滚动位置

94

有人可以告诉我我做错了什么吗?我需要在一定时间后刷新我的页面,但是它总是刷新到页面顶部,我不希望改变页面位置!这是我现在的代码,但它没有起作用。是标签的问题吗?这是我目前使用的代码,但仍然没有刷新。一定是哪里出错了吧?

以下是我最初的代码...

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="refresh" content="72">
        <meta http-equiv="Pragma" CONTENT="no-cache">
        <meta http-equiv="Expires" CONTENT="-1">

        <style type="text/css">
        body
        { 
            background-image: url('../Images/Black-BackGround.gif');
            background-repeat: repeat;
        }
        </style>
    </head>

    <script type="text/javascript">

    function saveScrollPositions(theForm) {
        if(theForm) {
            var scrolly = typeof window.pageYOffset != 'undefined' ? window.pageYOffset
                                                   : document.documentElement.scrollTop;
            var scrollx = typeof window.pageXOffset != 'undefined' ? window.pageXOffset
                                                  : document.documentElement.scrollLeft;
            theForm.scrollx.value = scrollx;
            theForm.scrolly.value = scrolly;
        }
    }
    </script>

 <form action="enroll.php" name="enrollment" method="post" onsubmit="return saveScrollPositions (this);">
  <input type="hidden" name="scrollx" id="scrollx" value="0" />
  <input type="hidden" name="scrolly" id="scrolly" value="0" />

  <STYLE type="text/css">
   #Nav a{ position:relative; display:block; text-decoration: none; color:Black; }
   Body td{font-Family: Arial; font-size: 12px; }
  </style>

阅读了一些初始答案后,我将它修改为这样...
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>

<style type="text/css">
body
{ 
    background-image: url('../Images/Black-BackGround.gif');
    background-repeat: repeat;
}
</style>
</head>


<script>
function refreshPage () {
    var page_y = $( document ).scrollTop();
    window.location.href = window.location.href + '?page_y=' + page_y;
}
window.onload = function () {
    setTimeout(refreshPage, 35000);
    if ( window.location.href.indexOf('page_y') != -1 ) {
        var match = window.location.href.split('?')[1].split("&")[0].split("=");
        $('html, body').scrollTop( match[1] );
    }
}
</script>

<STYLE type="text/css">
#Nav a{ position:relative; display:block; text-decoration: none; color:black; }
Body td{font-Family: Arial; font-size: 12px; }
</style>

2
尝试使用本地存储进行保存。 - Shawn31313
1
我该怎么做,你能用我现有的东西展示给我看吗? - chriswiec
另一个可能的解决方案是将你的/cards/:id路由呈现为全屏模态框,并将/cards路由保持在其后面。答案链接在这里 - Gabriel Arghire
10个回答

74

这可以起到魔法的作用

    <script>
        document.addEventListener("DOMContentLoaded", function(event) { 
            var scrollpos = localStorage.getItem('scrollpos');
            if (scrollpos) window.scrollTo(0, scrollpos);
        });

        window.onbeforeunload = function(e) {
            localStorage.setItem('scrollpos', window.scrollY);
        };
    </script>

13
非常好的简单解决方法。我做了一些改动。即使在浏览器关闭后,浏览器仍然会存储这些数据。我用sessionStorage替换了localStorage,并在设置滚动位置后使用sessionStorage.removeItem('scrollpos')清除它。这确保了浏览器关闭后滚动位置被清除。我将修改后的代码发布为单独的答案。 - Ben
2
如果你想要保持像div这样的元素的滚动位置,你可以使用同样的技巧来设置元素的scrollTop属性。 - Joe

57

document.location.reload()保存了位置信息,详情请见文档.

添加额外的true参数以强制重新加载,但不恢复位置。

document.location.reload(true)

MDN文档:

forcedReload标志会改变某些浏览器处理用户滚动位置的方式。通常,reload()之后会恢复滚动位置,但强制模式下可能会将滚动位置滚动回页面顶部,就好像window.scrollY === 0一样。


2
现在在MDN上已经提到了这一点。 - trysis
2
@trysis 哪里?在https://developer.mozilla.org/en-US/docs/Web/API/Location/reload$compare 上看不到?locale=en-US&to=788646&from=471047 - powtac
2
它在你回答中链接的页面上。他们称其为“forcedReload”。 - trysis
2
文档中说:“在强制模式下(当参数设置为true时),新的DOM将以scrollTop == 0加载。” - 这听起来并不像它会保持滚动位置。我还没有时间测试它,所以我可能错过了什么... - Daryn
4
只有在Chrome中可以使用,最新版本的Firefox和Edge不能保持滚动位置,相反会滚动到顶部。 - g.pickardou
显示剩余3条评论

18

我修改了Sanoj Dushmantha的答案,使用sessionStorage代替localStorage。然而,尽管有文档说明,浏览器仍会在关闭后继续存储这些数据。为解决这个问题,在滚动位置重置后,我将删除它。

<script>
    document.addEventListener("DOMContentLoaded", function (event) {
        var scrollpos = sessionStorage.getItem('scrollpos');
        if (scrollpos) {
            window.scrollTo(0, scrollpos);
            sessionStorage.removeItem('scrollpos');
        }
    });

    window.addEventListener("beforeunload", function (e) {
        sessionStorage.setItem('scrollpos', window.scrollY);
    });
</script>

1
非常有用,谢谢!我有两个问题,在尝试维护scrollPosition时,是否可以避免在每次加载/刷新时看到小的过渡动画?此外,它会在选项卡之间共享吗?如何处理多个选项卡中的会话?为每个页面创建唯一的键名是否对Web性能产生重大影响? - NcXNaV

16
如果您不想使用本地存储,那么可以将页面的y位置附加到URL上,并在加载时使用js进行获取,并将页面偏移设置为传递的get参数,例如:
//code to refresh the page
var page_y = $( document ).scrollTop();
window.location.href = window.location.href + '?page_y=' + page_y;


//code to handle setting page offset on load
$(function() {
    if ( window.location.href.indexOf( 'page_y' ) != -1 ) {
        //gets the number from end of url
        var match = window.location.href.split('?')[1].match( /\d+$/ );
        var page_y = match[0];

        //sets the page offset 
        $( 'html, body' ).scrollTop( page_y );
    }
});

为保存功能添加以下代码://code to refresh the page var page_y = $( document ).scrollTop(); window.location.href = window.location.href + '?page_y=' + page_y;,以刷新页面。 - Shawn31313
@chrisw.iec,我添加了一个新答案。 - Shawn31313
@Shawn31313 我没有看到接受编辑的方式?我是这个网站的新手...你说得对,我匆忙写了这个代码,虽然有indexOf但应该写成 if( window.location.href.indexOf( 'page_y' ) !== -1 ) 而且match变量是正则表达式,这里是我的表达式测试用例链接 regexr,它匹配字符串末尾的任意长度数字,也就是page_y参数的值。 - kkemple
@Shawn31313,你的编辑被拒绝了,但我更新了错误的indexOf部分,然而我保留了关于正则表达式匹配的部分,因为那是一个正确的正则表达式,并且会产生与你建议的更改相同的效果。 - kkemple
1
@kkemple 但是也匹配:?sadjsaid332 或 ?2332 ... 另外,我不是在提到 RegExp.. 我是在谈论 .split['?'] << 这是不正确的。 - Shawn31313
显示剩余6条评论

9

更新

你可以使用下面提到的document.location.reload(true)来代替下面的强制性技巧。

用以下HTML代码替换你的内容:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">
            body { 
                background-image: url('../Images/Black-BackGround.gif');
                background-repeat: repeat;
            }
            body td {
               font-Family: Arial; 
               font-size: 12px; 
            }
            #Nav a { 
                position:relative; 
                display:block; 
                text-decoration: none; 
                color:black; 
            }
        </style>
        <script type="text/javascript">
            function refreshPage () {
                var page_y = document.getElementsByTagName("body")[0].scrollTop;
                window.location.href = window.location.href.split('?')[0] + '?page_y=' + page_y;
            }
            window.onload = function () {
                setTimeout(refreshPage, 35000);
                if ( window.location.href.indexOf('page_y') != -1 ) {
                    var match = window.location.href.split('?')[1].split("&")[0].split("=");
                    document.getElementsByTagName("body")[0].scrollTop = match[1];
                }
            }
        </script>
    </head>
    <body><!-- BODY CONTENT HERE --></body>
</html>

1
在 Firefox 上无法工作(scrollTop 始终为零),因此我使用了 这个 - Sanjay Sahani
1
我无法在IE 11中使其工作。我在body中添加了一堆这样的内容:<a href="#">sadsad</a><br>但是当我点击链接时,我跳转到页面顶部。 - Stig Eide

7
这也可能对刷新页面有用。但如果您想在单击相同位置之前跟踪页面上的位置,则以下代码将有所帮助。
还添加了数据确认以提示用户是否真的想要这样做。
注意:我正在使用jQuery和js-cookie.js来存储cookie信息。
$(document).ready(function() {
    // make all links with data-confirm prompt the user first.
    $('[data-confirm]').on("click", function (e) {
        e.preventDefault();
        var msg = $(this).data("confirm");
        if(confirm(msg)==true) {
            var url = this.href;
            if(url.length>0) window.location = url;
            return true;
        }
        return false;
    });

    // on certain links save the scroll postion.
    $('.saveScrollPostion').on("click", function (e) {
        e.preventDefault();
        var currentYOffset = window.pageYOffset;  // save current page postion.
        Cookies.set('jumpToScrollPostion', currentYOffset);
        if(!$(this).attr("data-confirm")) {  // if there is no data-confirm on this link then trigger the click. else we have issues.
            var url = this.href;
            window.location = url;
            //$(this).trigger('click');  // continue with click event.
        }
    });

    // check if we should jump to postion.
    if(Cookies.get('jumpToScrollPostion') !== "undefined") {
        var jumpTo = Cookies.get('jumpToScrollPostion');
        window.scrollTo(0, jumpTo);
        Cookies.remove('jumpToScrollPostion');  // and delete cookie so we don't jump again.
    }
});

一个使用它的示例。
<a href='gotopage.html' class='saveScrollPostion' data-confirm='Are you sure?'>Goto what the heck</a>

这个答案有点冗长,但我仍然喜欢它。我能够通过 cookie 检查和以下两行代码实现:var currentYOffset = window.pageYOffset; // 保存当前页面位置。Cookies.set('jumpToScrollPostion', currentYOffset); - Steve Scott

7

感谢Sanoj,那对我有用。
然而,在iPhone上,iOS不支持“onbeforeunload”。对我来说解决办法是使用JS设置localStorage。

<button onclick="myFunction()">Click me</button>

<script>
document.addEventListener("DOMContentLoaded", function(event) { 
            var scrollpos = localStorage.getItem('scrollpos');
            if (scrollpos) window.scrollTo(0, scrollpos);
        });
function myFunction() {
  localStorage.setItem('scrollpos', window.scrollY);
  location.reload(); 
}
</script>

3
我找到了一个非常简单的解决方案。只需在链接的HREF标记中添加一个ID链接作为单独的参数即可。
<a class="page-link" href="{{ url_for('events.home', page=page_num) }}, #past_events">

那个链接指向我想保持焦点的

顶部。


目前为止,这是最简单的解决方案。 - Vladan
只有在您的元素上使用ids时才需要这样做。 - Artur Müller Romanov

1
如果您需要定位到某个页面的特定滚动位置而不是重新加载页面,可以使用带有id属性的元素进行标记:


<h1 id="success">Kontakt</h1>

并且从js重定向到URL:

window.location.href = '/contact#success'

或者从 html 中获取 (@Chris的答案):

<a href="/contact#success"></a>

0

这是我写过的最简单的代码。

永远不要使用Page.MaintainScrollPositionOnPostBack = True,它完全没有用处。

这就是你需要维护位置的所有脚本。将其添加到任何页面或主页面(如果您正在使用主页面)。

<script type="text/javascript">

    function setScreen() {
        var yScreen = localStorage.getItem("yPos");
        window.scrollTo(0, yScreen);
    }
    function setScroll() {
        var yScroll = window.pageYOffset;
        localStorage.setItem("yPos", yScroll);
    }
    function clearScreen() {
        localStorage.setItem("yPos", 0);
        window.scrollTo(0, 0);
    }

</script>

在 body 标签上添加 onscroll="setScroll()" onload="setScreen()"

<body onscroll="setScroll()" onload="setScreen()">

当用户返回您的网站时,要重置滚动条,需要重置本地存储。

将此代码添加到Default.aspx页面,然后将用户重定向到任何您想要的页面。

<script type="text/javascript">

    function resetScroll() {
        localStorage.setItem("yPos", 0);
    location.replace("somepage.aspx")
        }
    }

</script>

在该页面的body标签中添加onload="resetScroll()"。
<body onload="resetScroll()">

我花了大约2个小时来编写、调试和发布这段代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接