2

我们将 Durandal 用于我们的 SPA 应用程序,在我看来,这是一个常见的用例。我们有两个页面:一个页面是实体列表(带有过滤器、排序、虚拟滚动),另一个是实体的详细预览。因此,用户在列表页面上并设置了一个过滤器,结果列表就出来了。向下滚动一点后,用户会注意到一个他/她想查看详细信息的实体。因此,单击适当的链接用户将导航到详细信息预览页面。

在预览页面上的“工作完成”后,用户单击返回按钮(在应用程序本身或浏览器中),他/她回到列表页面。但是,默认的“入口”转换会将页面滚动到顶部,而不是滚动到列表中用户按下预览的位置。因此,为了“阅读”列表,用户必须在按下预览之前向下滚动他/她所在的位置。

所以我开始创建新的过渡,它将为某些页面(如列表搜索页面)保持滚动位置,而对于其他页面(如预览或编辑页面)在过渡完成时滚动到顶部。这很容易做到,然而,当我注意到当我点击navigateBack'按钮'时预览页面上有奇怪的行为时,我感到很惊讶。我已经长话短说,经过调查,我发现 windows.history.back 更早完成,然后进行转换,这导致预览页面在按下后退按钮时自动向下滚动到上一个(列表)页面的位置。这种滚动对 UI 产生了非常不愉快的影响,更不用说这对我的过渡来说是“彻底的灾难”。

有什么想法或建议在这种情况下我能做什么?

这是转换的代码。就我遇到这个问题而言,它只是一个尚未完成的工作副本。

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;

});

4

1 回答 1

0

更简单的方法是在模块停用时存储滚动位置并在 viewAttached 上恢复滚动。

您可以将位置存储在一些全局应用程序变量中:

app.scrollPositions = app.scrollPositions || {};
app.scrollPositions[system.getModuleId(this)] = theCurrentScrollPosition;

于 2014-01-22T02:24:26.020 回答