在没有$ scope的情况下修改范围不起作用。$ apply

时间:2015-08-09 10:33:38

标签: javascript angularjs

我有一个按钮的指令,当点击它时会显示一个加载屏幕。

angular.module('randomButton', ['Data'])

.directive('randomButton', function(Data) {
     return {
        scope: '=',
        restrict: 'A',
        templateUrl: 'templates/components/randomButton.html',
        link: function(scope, element, attrs){

            element.click(function(){
                scope._loading();
            });

        }
    }
});

它通过调用另一个指令中包含的范围上的另一个函数来实现:

angular.module('quoteContainer', [])

.directive('quoteContainer', function(Data) {

    function quoteController($scope){

        $scope._loading = function(){
            console.log('loading');
            $scope.loadMessage = Data.getRandomText();
            $scope.loading = true;              
        };

    }

    return {
        scope: '=',
        restrict: 'A',
        templateUrl: 'templates/components/quoteContainer.html',
        controller: ['$scope', quoteController],
        link: function(scope,element,attrs){

        }
    }
});

我的问题是,要发生此更改,我必须在$scope.$apply函数中调用._loading()。例如:

$scope._loading = function(){
    console.log('loading');
    $scope.$apply(function(){
        $scope.loadMessage = Data.getRandomText();
        $scope.loading = true;              
    });         
};

我理解这是不好的做法,只应在与其他框架/ ajax调用等接口时使用。那么为什么我的代码拒绝在没有$scope.$apply的情况下工作,如何在没有它的情况下使其工作?

1 个答案:

答案 0 :(得分:1)

基本上你需要让角度知道变化发生的某种方式,因为因为它在异步事件处理程序中,因此角度通常用于注意变化的机制并不适用于它。

因此需要将其包装在$apply中,这会在代码运行后触发摘要周期,从而使角度有机会根据新数据进行更改。但是,这样做的首选方法是使用angular的内置$timeout服务,它有效地做同样的事情(即将代码包装在$apply块中),但是没有问题的可能性其他摘要周期可能会在触发时持续进行。

您可以像使用$ apply一样使用它:

$timeout(function(){
    $scope.loadMessage = Data.getRandomText();
    $scope.loading = true;              
});         

(如果您确实想延迟值的应用,可能需要第二个参数,但在您的情况下则不需要。)