我在 MVC 中从事一个项目,并且很喜欢学习它。有一些成长的痛苦,但一旦你弄清楚它们就不错了。在 WebForms 世界中真正简单的一件事是保持页面上的滚动位置。您只需将 MaintainScrollPositionOnPostback 属性设置为 true。但是,在 MVC 中,我不使用回发,所以这对我不起作用。处理这个的标准方法是什么?
编辑: Ajax 是可以接受的,但我也想知道如果没有 AJAX 你会怎么做。
我在 MVC 中从事一个项目,并且很喜欢学习它。有一些成长的痛苦,但一旦你弄清楚它们就不错了。在 WebForms 世界中真正简单的一件事是保持页面上的滚动位置。您只需将 MaintainScrollPositionOnPostback 属性设置为 true。但是,在 MVC 中,我不使用回发,所以这对我不起作用。处理这个的标准方法是什么?
编辑: Ajax 是可以接受的,但我也想知道如果没有 AJAX 你会怎么做。
我已经在 JS 中解决了这个问题:
$(document).scroll(function(){
localStorage['page'] = document.URL;
localStorage['scrollTop'] = $(document).scrollTop();
});
然后在准备好的文件中:
$(document).ready(function(){
if (localStorage['page'] == document.URL) {
$(document).scrollTop(localStorage['scrollTop']);
}
});
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 无论如何都应该避免回发。
实际上没有标准的处理方式,这是微软为了支持他们的回发模型而进行的黑客攻击。他们需要这个,因为每个控件都会发回一个帖子,并且用户会不断地被推回页面顶部。
与 MVC 一起使用的建议是使用 AJAX 将您的大部分回帖返回到服务器。这样页面就不必重新渲染焦点不会移动。jQuery 让 AJAX 变得非常简单,甚至还有默认的表单,比如
<% Ajax.BeginForm(...) %>
它将为您处理 AJAX 方面的事情。
从 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 进行滚动,因此它可以正常工作并且应该是跨浏览器安全的。我相信提供的代码是不言自明的,但我很乐意提供更详细的描述,让我知道。
我自己的解决方法是使用一些信息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
来确定必须重新定位视图页面中的哪些元素。
希望能帮助到你。
我在标签中使用了名称属性。没有使用 JavaScript。
我想返回的页面有 <a> 带有 name 属性的标签,例如 <a name="testname">。
我从使用标签 <a href="<%: Request.UrlReferrer %>#testname">Back</a>" 返回的页面(视图)。Request.UrlReferrer 用于转到上一页。#testname 滚动页面用名称“testname”标记的位置。
<%
if(!ViewData.ModelState.IsValid)
{
%>
window.location.hash = 'Error';
<%
}
%>
<a name="Error"></a>
这是一个简单的纯 Javascript 解决方案,我仅在 FF4 和 IE9 中测试过。
这个想法是,这个解决方案应该通过回退到#anchor
页面上的标准标签来优雅地降级。我正在做的是用#anchor
X 和 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];
}
这符合我的需求,但可能更通用/可重用 - 我很高兴有人对此进行改进...... :-)
一个非常不好的方法是使用 cookie。
如果您在 MVC 中使用一个页面来处理其他页面,您可以为其添加一个代码片段,以加载每个页面,该页面会创建一个名为“scrolltop”的 cookie(如果不存在)。当用户向上或向下滚动时,通过捕获这些事件或查看 scrollTop 值,有一些方法可以让 javascript 自动更新此 cookie。
在一个新页面上,您只需要加载保存的位置并让视图在 0 毫秒内滚动到那里(使用 Mootools 或任何 Ajax 脚本,这应该是可能的),用户将准确地回到他们所在的位置。
我对asp了解不多,所以我不知道是否存在锚定到当前y位置的方法。Javascript 是一种快速简便的方法。如果您已锚定每个元素并将锚点发布到其他页面,则 HTMl 中的锚点可能是一种选择。
我使用 .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 值。最后,您的页面将表现得像网络表单,一切都保持不变。
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...
}
}
这将滚动回表单的顶部,这样任何错误消息都将可见,因为您可能已经滚动到验证摘要之外。
@{
}
<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