我们正在使用Durandal进行SPA应用,并且在我看来,它是常见的用例。我们有两个页面:一个页面是实体列表(带有过滤器,排序,虚拟滚动),另一个页面是实体的详细预览。因此,用户在列表页面上并设置过滤器并显示结果列表。滚动一点点后,用户会注意到他/她想要查看详细信息的实体。因此,单击正确的链接用户将导航到详细信息预览页面。
在预览页面上“完成工作”后,用户单击后退按钮(在应用程序本身或浏览器中),他/她回到列表页面上。但是,默认的“入口”转换将页面滚动到顶部而不是用户按下预览的列表上的位置。因此,为了“阅读”列表,用户必须在按下预览之前向下滚动他/她。
所以我开始创建新的转换,对于某些页面(如列表搜索页面)保持滚动位置,其他页面(如预览或编辑页面)在转换完成时滚动到顶部。然而这很容易做到,当我注意到当我点击navigateBack'按钮'时预览页面上有奇怪的行为时,我感到很惊讶。我已经很久了,经过调查我发现windows.history.back早先完成了转换,这导致预览页面在按下后退按钮时自动滚动到上一个(列表)页面的位置。这种滚动对用户界面产生了非常不愉快的影响,没有提到它对我的过渡来说是“彻头彻尾的灾难”。
在这种情况下,我有什么想法或建议?
以下是过渡代码。就这个问题而言,这只是一个尚未完成的工作副本。
define(['../system'], function (system) {
var fadeOutDuration = 100;
var scrollPositions = new Array();
var getScrollObjectFor = function (node) {
var elemObjs = scrollPositions.filter(function (ele) {
return ele.element === node;
});
if (elemObjs.length > 0)
return elemObjs[0];
else
return null;
};
var addScrollPositionFor = function (node) {
var elemObj = getScrollObjectFor(node);
if (elemObj) {
elemObj.scrollPosition = $(document).scrollTop();
}
else {
scrollPositions.push({element: node, scrollPosition: $(document).scrollTop()});
}
};
var scrollTransition = function (parent, newChild, settings) {
return system.defer(function (dfd) {
function endTransition() {
dfd.resolve();
}
function scrollIfNeeded() {
var elemObj = getScrollObjectFor(newChild);
if (elemObj)
{
$(document).scrollTop(elemObj.scrollPosition);
}
else {
$(document).scrollTop(0);
}
}
if (!newChild) {
if (settings.activeView) {
addScrollPositionFor(settings.activeView);
$(settings.activeView).fadeOut(fadeOutDuration, function () {
if (!settings.cacheViews) {
ko.virtualElements.emptyNode(parent);
}
endTransition();
});
} else {
if (!settings.cacheViews) {
ko.virtualElements.emptyNode(parent);
}
endTransition();
}
} else {
var $previousView = $(settings.activeView);
var duration = settings.duration || 500;
var fadeOnly = !!settings.fadeOnly;
function startTransition() {
if (settings.cacheViews) {
if (settings.composingNewView) {
ko.virtualElements.prepend(parent, newChild);
}
} else {
ko.virtualElements.emptyNode(parent);
ko.virtualElements.prepend(parent, newChild);
}
var startValues = {
marginLeft: fadeOnly ? '0' : '20px',
marginRight: fadeOnly ? '0' : '-20px',
opacity: 0,
display: 'block'
};
var endValues = {
marginRight: 0,
marginLeft: 0,
opacity: 1
};
$(newChild).css(startValues);
var animateOptions = {
duration: duration,
easing : 'swing',
complete: endTransition,
done: scrollIfNeeded
};
$(newChild).animate(endValues, animateOptions);
}
if ($previousView.length) {
addScrollPositionFor(settings.activeView);
$previousView.fadeOut(fadeOutDuration, startTransition);
} else {
startTransition();
}
}
}).promise();
};
return scrollTransition;
});
答案 0 :(得分:0)
更简单的方法是在模块停用时存储滚动位置并恢复viewAttached上的滚动。
您可以将这些职位存储在某个全局app变量中:
app.scrollPositions = app.scrollPositions || {};
app.scrollPositions [system.getModuleId(this)] = theCurrentScrollPosition;