AngularJS - 将函数调用延迟到完整的浏览器渲染,直到viewmodel同步循环结束

时间:2013-04-02 09:32:37

标签: javascript angularjs angularjs-scope

我不确定这个问题的正确标题是什么,所以如果我错了请纠正我。

让我们说在页面刷新(加载)时我需要根据当前位置的哈希执行动画滚动来锚定(我知道ngAnchorScroll,但我需要一个动画的scolling, ngAnchorScorll无法做到。)

为此,我实现了一项服务,该服务将在控制器初始化时调用:

var Ctrl = function ($scope, initAnchorScrolling) {
    initAnchorScrolling($scope);
};

Ctrl.$inject = ['$scope', "initAnchorScrolling"];

applicationServices.factory("initAnchorScrolling",
    ['scroll', '$location', '$timeout', function(scrollUtils, $location, $timeout) {
    return function(scope) {

    /** Some stuff here */

    function scroll() {
        var hash = $location.hash(), elm;

        if (!hash) {
            scrollUtils.scrollTo(0, 0);
        } else if ((elm = getAnchorElement(hash))) {
            scrollUtils.scrollToElement(elm);
        } else {
            scrollUtils.scrollTo(0, 0);
        }
    }

    scope.$watch(function scrollWatch() { return $location.hash(); },
        function scrollWatchAction() {
            $timeout(function () {
                scroll();
            }, 0, true);
        });
    };
}]);

您可能会看到此锚点的实现与ngAnchorScroll的实现非常相似。主要区别在于我使用jQuery.animate()在锚之间移动。

正如我从here理解延迟函数执行直到当时浏览器完成渲染时,我们只需要使用延迟参数调用$ timeout服务,该参数等于0.但这对我不起作用。零星的页面滚动到不同的位置。我可以这样解释 - 在摘要周期完成视图和模型同步之前调用的滚动函数,所以在调用时,HTML块的高度和位置都无效。

所以我的问题是:是否有可能推迟函数调用直到浏览器完全完成渲染并且摘要周期完成同步的视图和模型(应用绑定)?

1 个答案:

答案 0 :(得分:0)

最初的问题是关于滚动到特定哈希,而这个解决方案是关于保留滚动位置,无论如何。它仍然可以为您提供解决方案

我创建了一个适用于窗口滚动的指令(它可以更新为可以处理任何元素)

html用法

<div ng-keep-scroll="service.scrollY">
<!-- list of scrolling things here -->
</div>

其中“service.scrollY”必须是服务中的变量。服务保留其状态和值,每次加载和清除其值时都会重新创建控制器,因此您无法使用它们来存储持久数据。控制器有一个指向服务的范围变量。

指令js

app.directive('ngKeepScroll', function ($timeout) {
    return function (scope, element, attrs) {

        //load scroll position after everything has rendered
        $timeout(function () {
            var scrollY = parseInt(scope.$eval(attrs.ngKeepScroll));
            $(window).scrollTop(scrollY ? scrollY : 0);
        }, 0);

        //save scroll position on change
        scope.$on("$routeChangeStart", function () {
            scope.$eval(attrs.ngKeepScroll + " = " + $(window).scrollTop());
        });
    }
});