首页 文章

AngularJS在更新数组时没有刷新ngRepeat

提问于
浏览
30

我有时会对AngularJS有严重的麻烦 . 所以我的控制器中有一个基本数组

$scope.items = ["a","b","c"]

我正在我的模板中重复项目数组ng-repeat =“item in items” . 到目前为止超级直播 . 经过几次UX操作后,我想将一些新东西推送到我的阵列 .

$scope.items.push("something");

因此,50%的时间,新元素被添加到视图中 . 但其他50%,没有任何反应 . 这就像超级令人沮丧; bc如果我在$ scope中包装它 . $ apply(),我得到了“$ digest in progress”错误 . 将其包装到$ timeout也无济于事 .

当我使用Chrome扩展程序检查我的元素范围时;我可以看到新数据在那里,$ scope.items值是正确的 . 但是视图并没有考虑将其添加到DOM中 .

谢谢!

3 回答

  • 4

    您将在50%的时间内在angular的 $digest 循环之外修改范围 .

    如果有回调不是来自angularjs; (可能是jquery) . 你需要调用 $apply 来强制 $digest 循环 . 但是在 $digest 循环中你不能调用 $apply 因为你所做的每一个改变都会自动反映出来 .

    您需要知道回调何时不是来自角度,并且应该只调用 $apply .

    如果您不知道也无法学习,这里有一个巧妙的诀窍:

    var applyFn = function () {
        $scope.someProp = "123";
    };
    if ($scope.$$phase) { // most of the time it is "$digest"
        applyFn();
    } else {
        $scope.$apply(applyFn);
    }
    
  • 0

    正如UmurKontacı所指出的,您有时会在摘要周期之外进行模型更改 . 但是,我建议您确保这种情况永远不会发生,而不是解决此问题并尝试检测您是否处于应用/摘要上下文中 .

    导致此问题的主要原因是您的函数被调用为对DOM事件的反应 . 例如 .

    jQuery('.some-element').click(function() { seeminglyProblematicCode() })
    

    这是你的$ apply()需要去的地方,而不是在函数内 . 否则,您的整个代码迟早会被这些区别所困扰 . 假设在此事件处理程序的上下文中有一个范围,您可以编写:

    jQuery('.some-element').click(function() { 
        $scope.$apply(function() { seeminglyProblematicCode() })
    })
    

    但是,您必须注意一个警告:当您从代码中触发单击事件时,您将遇到摘要周期已在进行中的问题 . 这是你需要$ timeout的地方 . this question的答案很好地解决了这个问题 .

  • 21

    我有同样的问题,我的解决方法是观察在嵌套指令中调用哪些控制器 .

    # Parent Controller
    app.controller 'storeController', ($scope, products) ->
    
      $scope.cart = ["chicken", "pizza"]
      $scope.addToCart = (item) ->
        $scope.cart.push item
    
      # from service
      products.get().then (items) ->
        $scope.products = items
    
    # Parent Directives
    app.directive 'storeContainer', ($scope, config) ->
      restrict: 'E'
      templatUrl: 'store-container.html'
      controller: 'storeController'
    
    # Nested Directive
    app.directive 'storeFront', ($scope, config) ->
      restrict: 'E'
      templatUrl: 'store-front.html'
      controller: 'storeController'
    
    # Parent Template templates/directives/store-container.html
    <div ng-repeat="item in cart">{{ item }}</div>
    <strore-front></store-front>
    
    # Nested Template templates/directives/store-front.html
    <ul ng-repeat="item in products">
      <li ng-click"addToCart(item)">{{ item }}</li>
    </ul>
    

    这里的错误是嵌套指令在原型链中创建第二个控制器(storeController的副本),父模板无权访问 . 要解析写嵌套控制器,如下所示:

    # Nested Directive
    app.directive 'storeFront', ($scope, config) ->
      restrict: 'E'
      templatUrl: 'store-front.html'
    

    有更好的方法来创建继承链,但这将解决许多人学习AngularJS的问题 .

相关问题