Angular无法更新绑定的属性

3

演示链接

HTML:

<div ng-controller="MyCtrl">
    <button my-event-directive>Click me</button>
    <div>{{secret}}</div>
</div>

JS:

var myApp = angular.module('myApp',[]);

myApp.directive('myEventDirective', function() {
      return {
        link: function(scope, element) {
            element.on('click', function(event){
                scope.$emit('myEvent', {secret: 'aaa'}); 
            });
        }
      }
})

function MyCtrl($scope) {
    $scope.secret = 'bbb';
    $scope.$on('myEvent', function(event, data){
        alert('event received!');
        $scope.secret = data.secret;
    });
}

当我点击按钮时,在控制器中接收到了事件(弹出警告)。然而,{{secret}} 绑定并没有更新其值。为什么?

当然,在真实的代码中,我的事件创建更加复杂。


3
你可以总是使用 $apply :http://jsfiddle.net/HB7LU/5325/(注:$apply 是 AngularJS 框架中的一个函数,用于将数据模型的变化同步到视图层。) - Ivan Chernykh
可以运行!请将其发布为答案,以便我可以接受它。值得一读:http://jimhoskins.com/2012/12/17/angularjs-and-apply.html - fracz
太好了,很高兴能帮到你!(抱歉我现在没有时间回答问题) - Ivan Chernykh
3个回答

3

正如@Cherinv在评论中所回答的那样,当在Angular的$apply方法之外更改作用域属性时,您必须手动调用它。@runTarm还建议事件分派程序应该使用$apply,因为监听器从中解脱出来并记得它。因此:

scope.$emit('myEvent', {secret: 'aaa'});

应该更改为:

scope.$apply(function() {
    scope.$emit('myEvent', {secret: 'aaa'});
});

$apply 方法在下面的文章中有详细描述:http://jimhoskins.com/2012/12/17/angularjs-and-apply.html


1
实际上,$scope.apply() 应该在事件源处,我的意思是在 scope.$emit() 之后或包装它,而不是在监听器内部。 - runTarm

1

使用 $scope.$apply()。现在更改将被注意到,页面将更新。

var myApp = angular.module('myApp',[]);

        myApp.directive('myEventDirective', function() {
              return {
                link: function(scope, element) {
                    element.on('click', function(event){
                        scope.$emit('myEvent', {secret: 'aaa'}); 
                    });
                }
              }
        })

        function MyCtrl($scope) {
            $scope.secret = 'bbb';
            $scope.$on('myEvent', function(event, data){
                alert('event received! secret is ' + data.secret);

                 $scope.$apply(function () {
                    $scope.secret = data.secret;        
                 });
            });
        }

0
你可以尝试将绑定更改为发生在 object.value 而不是 value 上。也许这是 Angular 无法跟踪不可变属性更改的情况。
<div ng-controller="MyCtrl">
    <button my-event-directive>Click me</button>
    <div>{{data.secret}}</div>
</div>

var myApp = angular.module('myApp',[]);

myApp.directive('myEventDirective', function() {
      return {
        link: function(scope, element) {
            element.on('click', function(event){
                scope.$emit('myEvent', {secret: 'aaa'}); 
            });
        }
      }
})

function MyCtrl($scope) {
    $scope.data = {
        secret: 'bbb'
    };
    $scope.$on('myEvent', function(event, data){
        alert('event received!');
        $scope.data.secret = data.secret;
    });
}

这应该可以工作。

P.S. 由于您总是看到 alert 被调用,这意味着您不需要调用 scope.$apply 来调用 scope digest 并分配值,问题在于 Angular 无法监视不可变值(可能)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接