28

我在 MVC 中从事一个项目,并且很喜欢学习它。有一些成长的痛苦,但一旦你弄清楚它们就不错了。在 WebForms 世界中真正简单的一件事是保持页面上的滚动位置。您只需将 MaintainScrollPositionOnPostback 属性设置为 true。但是,在 MVC 中,我不使用回发,所以这对我不起作用。处理这个的标准方法是什么?

编辑: Ajax 是可以接受的,但我也想知道如果没有 AJAX 你会怎么做。

4

12 回答 12

54

我已经在 J​​S 中解决了这个问题:

$(document).scroll(function(){
    localStorage['page'] = document.URL;
    localStorage['scrollTop'] = $(document).scrollTop();
});

然后在准备好的文件中:

$(document).ready(function(){
    if (localStorage['page'] == document.URL) {
        $(document).scrollTop(localStorage['scrollTop']);
    }
});
于 2013-04-25T08:10:01.767 回答
8

MaintainScrollPositionOnPostback 的工作方式是它有一对隐藏字段:__SCROLLPOSITIONX 和 __SCROLLPOSITIONY

在回发时,它设置这些,

function WebForm_GetScrollY() {
if (__nonMSDOMBrowser) {
    return window.pageYOffset;
}
else {
    if (document.documentElement && document.documentElement.scrollTop) {
        return document.documentElement.scrollTop;
    }
    else if (document.body) {
        return document.body.scrollTop;
    }
}
return 0;
}
function WebForm_SaveScrollPositionSubmit() {
    if (__nonMSDOMBrowser) {
        theForm.elements['__SCROLLPOSITIONY'].value = window.pageYOffset;
        theForm.elements['__SCROLLPOSITIONX'].value = window.pageXOffset;
    }
    else {
        theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX();
        theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY();
    }
    if ((typeof(this.oldSubmit) != "undefined") && (this.oldSubmit != null)) {
        return this.oldSubmit();
    }
    return true;
    }

然后它调用RestoreScrollPosition:

function WebForm_RestoreScrollPosition() {
    if (__nonMSDOMBrowser) {
        window.scrollTo(theForm.elements['__SCROLLPOSITIONX'].value, theForm.elements['__SCROLLPOSITIONY'].value);
    }
    else {
        window.scrollTo(theForm.__SCROLLPOSITIONX.value, theForm.__SCROLLPOSITIONY.value);
    }
    if ((typeof(theForm.oldOnLoad) != "undefined") && (theForm.oldOnLoad != null)) {
        return theForm.oldOnLoad();
    }
    return true;
}

但正如大多数人所说,MVC 无论如何都应该避免回发。

于 2009-02-04T17:49:40.357 回答
6

实际上没有标准的处理方式,这是微软为了支持他们的回发模型而进行的黑客攻击。他们需要这个,因为每个控件都会发回一个帖子,并且用户会不断地被推回页面顶部。

与 MVC 一起使用的建议是使用 AJAX 将您的大部分回帖返回到服务器。这样页面就不必重新渲染焦点不会移动。jQuery 让 AJAX 变得非常简单,甚至还有默认的表单,比如

<% Ajax.BeginForm(...) %>

它将为您处理 AJAX 方面的事情。

于 2009-01-27T18:20:02.427 回答
4

从 WebForms 和 Richard Gadsden 提供的答案中汲取灵感,另一种使用 javascript 和表单集合的方法可能如下所示:

@{
    var scrollPositionX = string.Empty;        
    if(IsPost) {
        scrollPositionX = Request.Form["ScrollPositionX"];
    }
}

<form action="" method="post">
    <input type="hidden" id="ScrollPositionX" name="ScrollPositionX" value="@scrollPositionX" />
    <input type="submit" id="Submit" name="Submit" value="Go" />
</form>

$("#Submit").click(function () {
    $("#ScrollPositionX").val($(document).scrollTop());
});

$("#ScrollPositionX").each(function () {
    var val = parseInt($(this).val(), 10);
    if (!isNaN(val))
        $(document).scrollTop(val);
});

提供的代码是为了灵感,绝不是美化的。它可能可以通过几种不同的方式完成,我想这一切都取决于您决定如何在 POST 中保留文档的 scrollTop 值。由于我们使用 jQuery 进行滚动,因此它可以正常工作并且应该是跨浏览器安全的。我相信提供的代码是不言自明的,但我很乐意提供更详细的描述,让我知道。

于 2011-07-13T19:57:01.057 回答
3

我自己的解决方法是使用一些信息ViewData来了解必须在后退导航中显示哪些区域,并使用一些 javascript 来定位页面的光标:

在视图中,像这样的元素:

<h3 id="tasks">
    Contained tasks
</h3>

以及重新定位页面的javascript:

<script type="text/javascript">
    addOnLoad(goAnchor);

    function goAnchor() {
        var paging = <%= //Here you determine (from the ViewData or whatever) if you have to position the element %>;
        if (paging == "True") {
            window.location.hash = "tasks";
        }
</script>

您可以使用 aswitch来确定必须重新定位视图页面中的哪些元素。

希望能帮助到你。

于 2009-01-27T18:14:59.630 回答
3

我在标签中使用了名称属性。没有使用 JavaScript。

我想返回的页面有 <a> 带有 name 属性的标签,例如 <a name="testname">。

我从使用标签 <a href="<%: Request.UrlReferrer %>#testname">Back</a>" 返回的页面(视图)。Request.UrlReferrer 用于转到上一页。#testname 滚动页面用名称“testname”标记的位置。

于 2011-01-18T06:42:35.860 回答
2
<%
   if(!ViewData.ModelState.IsValid)
   {
%>
   window.location.hash = 'Error';
<%
   }
%>

 <a name="Error"></a>
于 2010-06-15T04:36:30.820 回答
1

这是一个简单的纯 Javascript 解决方案,我仅在 FF4 和 IE9 中测试过。

这个想法是,这个解决方案应该通过回退到#anchor页面上的标准标签来优雅地降级。我正在做的是用#anchorX 和 Y 坐标动态替换这些标签,然后在加载时,我只需从查询字符串中读取这些值并在那里滚动。如果由于某种原因失败,浏览器仍应导航到该#anchor位置...

标记:

<a href="/somecontroller/someaction/#someanchor">My Link</a>

jQuery:

$(function() {

// RESTORE SCROLL POSITION
RestoreScrollPosition();

// SAVE SCROLL POSITION
$('a:not(a[href^="http"])').filter('[href$="#someanchor"]').each(function() {
    $(this).click(function() {
        var href = $(this).attr('href').replace("#someanchor","");
        if (href.indexOf('?') == -1) {
            href = href + '?x='
        } else {
            href = href + '&x='
        }
        href = href + window.pageXOffset;
        href = href + '&y=' + window.pageYOffset;
        $(this).attr('href', href);
    });
});
}

几个辅助方法:

function RestoreScrollPosition() {

    var scrollX = gup('x');
    var scrollY = gup('y');

    if (scrollX != null && scrollY != null) {
        window.scrollTo(scrollX, scrollY);
        return true;
    }
    return false;
}

function gup(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if (results == null)
        return "";
    else
        return results[1];
}

这符合我的需求,但可能更通用/可重用 - 我很高兴有人对此进行改进...... :-)

于 2011-05-08T23:10:41.427 回答
0

一个非常不好的方法是使用 cookie。

如果您在 MVC 中使用一个页面来处理其他页面,您可以为其添加一个代码片段,以加载每个页面,该页面会创建一个名为“scrolltop”的 cookie(如果不存在)。当用户向上或向下滚动时,通过捕获这些事件或查看 scrollTop 值,有一些方法可以让 javascript 自动更新此 cookie。

在一个新页面上,您只需要加载保存的位置并让视图在 0 毫秒内滚动到那里(使用 Mootools 或任何 Ajax 脚本,这应该是可能的),用户将准确地回到他们所在的位置。

我对asp了解不多,所以我不知道是否存在锚定到当前y位置的方法。Javascript 是一种快速简便的方法。如果您已锚定每个元素并将锚点发布到其他页面,则 HTMl 中的锚点可能是一种选择。

于 2009-01-27T18:25:04.197 回答
0

我使用 .scrollTop 如下所示,非常简单,它甚至可以在视图中使用多个表单(我的视图很长,分解为多个表单):

首先将此属性放入模型中:

               public string scrollTop { get; set; }

在视图中,在表格 #1 内:

               @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm1"})

在表格 #2 内:

               @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm2"})

在表格 #2 内:

               @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm3"})

然后在视图的底部:

 $(document).ready(function () {
    $(document).scrollTop(@Model.scrollTop);
    $(document).scroll(function () {
        $("#ScrollForm1").val($(document).scrollTop());
        $("#ScrollForm2").val($(document).scrollTop());
        $("#ScrollForm3").val($(document).scrollTop());
      });
   });

您的滚动位置始终在回发时保留,因为 @Html.HiddenFor 字段存储您当前的滚动并将其传递给发布时的模型。然后,当页面出现时,它会从模型中获取 scrollTop 值。最后,您的页面将表现得像网络表单,一切都保持不变。

于 2013-12-31T20:08:21.763 回答
0

10 年过去了,一个不同的 JS 解决方案。另一个 JS 解决方案等待页面滚动,当页面加载时滚动到保存的任何位置。这对大多数人来说都很好(尽管它不会删除该值,因此当您查看该页面时页面总是会滚动到该位置......)。我的解决方案是等待表单提交:

(是的,它使用的是 jQuery,但该网站有很多...)

    // OWNER'S FORM POSITION
    if ($("[js-owner-request]").length) {
        $("[js-owner-request]").on("submit", function() {
            localStorage['owner-request__scrollTop'] = $(this).offset().top;
        });

        if (localStorage['owner-request__scrollTop'] !== "null") {
            $(document).scrollTop(localStorage['owner-request__scrollTop']);
            localStorage['owner-request__scrollTop'] = "null"; // set to null so we don't always scroll...
        }
    }

这将滚动回表单的顶部,这样任何错误消息都将可见,因为您可能已经滚动到验证摘要之外。

于 2019-12-05T08:36:22.997 回答
-1

@{

}

<html>

<head>
    <script type="text/javascript">

window.onload = function () {
    var div = document.getElementById("dvScroll");
   var div_position = document.getElementById("div_position");
    var position = parseInt(@Request.Form("div_position"));
    if (isNaN(position)) {
        position = 0;
    }

    div.scrollTop = position;
    div.onscroll = function () {
        div_position.value = div.scrollTop;
    };
};

</script>
</head>

<body>

<div id="dvScroll" style="overflow-y: scroll; height: 260px; width: 300px">

    1. This is a sample text

    <br />

    2. This is a sample text

    <br />

    3. This is a sample text

    <br />

    4. This is a sample text

    <br />

    5. This is a sample text

    <br />

    6. This is a sample text

    <br />

    7. This is a sample text

    <br />

    8. This is a sample text

    <br />

    9. This is a sample text

    <br />

    10. This is a sample text

    <br />

    11. This is a sample text

    <br />

    12. This is a sample text

    <br />

    13. This is a sample text

    <br />

    14. This is a sample text

    <br />

    15. This is a sample text

    <br />

    16. This is a sample text

    <br />

    17. This is a sample text

    <br />

    18. This is a sample text

    <br />

    19. This is a sample text

    <br />

    20. This is a sample text

    <br />

    21. This is a sample text

    <br />

    22. This is a sample text

    <br />

    23. This is a sample text

    <br />

    24. This is a sample text

    <br />

    25. This is a sample text

    <br />

</div>

<hr />
<form method="post">
<input type="hidden" id="div_position" name="div_position" />
<input type="submit" value="Cool" />
    </form> 
</body>
</html>

您可以使用它在回发后保持滚动位置。

资料来源:http ://www.aspsnippets.com/Articles/Maintain-Scroll-Position-of-DIV-on-PostBack-in-ASPNet.aspx

于 2016-06-30T09:37:09.207 回答