31

AngularJSを理解するのに深刻な問題を抱えていることがあります。だから私は私のコントローラーに次のような基本的な配列を持っています

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

テンプレートで、items配列ng-repeat = "iteminitems"をngRepeatingしています。これまでのところ超ストレートフォワード。いくつかのUXアクションの後、いくつかの新しいものをアレイにプッシュしたいと思います。

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

したがって、50%の確率で、新しい要素がビューに追加されます。しかし、残りの50%は、何も起こりません。そして、それは非常に苛立たしいようなものです。bcそれを$scope。$apply()でラップすると、「$digestはすでに進行中です」というエラーが発生しました。それを$timeoutにラップしても役に立ちません。

また、Chrome拡張機能を使用して要素スコープを検査すると、新しいデータがあり、$scope.itemsの値が正しいことがわかります。しかし、ビューはそれをDOMに追加することを処理していません。

ありがとう!

4

3 に答える 3

21

angular の$digestサイクルの 50% の時間外でスコープを変更しています。

angularjs 以外からのコールバックがある場合。(おそらくjquery)。サイクル$applyを強制するには呼び出す必要があります。ただし、行ったすべての変更はすでに自動的に反映されているため、サイクル中に$digest呼び出すことはできません。$apply$digest

コールバックが角度からのものではない場合を知る必要があり、その場合に$applyのみ呼び出す必要があります。

わからない、または学ぶことができない場合は、ここに素晴らしいトリックがあります。

var applyFn = function () {
    $scope.someProp = "123";
};
if ($scope.$$phase) { // most of the time it is "$digest"
    applyFn();
} else {
    $scope.$apply(applyFn);
}
于 2013-03-22T13:15:30.247 に答える
4

Umur Kontacı が指摘したように、ダイジェスト サイクル外でモデルの変更を行っている場合があります。ただし、この問題を回避して適用/ダイジェスト コンテキストにいるかどうかを検出しようとする代わりに、これが起こらないようにすることをお勧めします。

この問題の主な原因は、関数が DOM イベントへの反応として呼び出されることです。例えば

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

これは、関数内ではなく、 $apply() が必要な場所です。そうしないと、遅かれ早かれ、コード全体にそのような区別が散らばってしまいます。このイベント ハンドラーのコンテキストにスコープがあると仮定すると、次のように記述できます。

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

ただし、注意が必要な点が 1 つあります。コードからクリック イベントをトリガーすると、ダイジェスト サイクルが既に進行中という問題が発生します。ここで $timeout が必要です。この質問への回答は、この問題を非常によくカバーしています。

于 2015-07-22T06:32:37.340 に答える
0

私は同じ問題を抱えていました.私の修正は、ネストされたディレクティブでどのコントローラーが呼び出されているかを監視することでした.

# 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 の複製) に 2 番目のコントローラーを作成することです。解決するには、ネストされたコントローラーを次のように記述します。

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

継承チェーンを作成するためのより良い方法がありますが、AngularJS を学習している多くの人々の問題はこれで解決されます。

于 2013-11-25T20:21:26.593 に答える