2016-12-06 2 views
2

ビューをサービスからデータにバインドする適切な方法は何ですか? 私は$ watchが落胆しているのを見ました。angle:ビューをサービスデータにバインドするのに適しています

私は、サービスから来た配列からアイテムをレンダリングするビューを持っています。

サービスは、定期的にデータが露出されたビューコントローラで

$http({...some params...}) 
.success(function(data) { 
    cache[key] = data; 
}); 

サーバーからのデータをリフレッシュします:

this.items = SomeFactory.cache[key] 

ビューが結合されています

ng-repeat="item in $ctrl.items" 

私の理解をcache[key]が新しい配列に割り当てられているので、ビューはstilですlは古いアドレスにバインドして更新されません。

とは何ですか?これを行う方法はありますか? 機能を使用してバインドすると機能します(例:ng-repeat="item in $ctrl.items()")。ただし、アイテムを変更するにはどうすればよいですか?パフォーマンスは賢明ではありませんか?

+0

ええと、それは更新しないのですか?私はそのように動作するように見える[プランカ](https://plnkr.co/edit/wcYonAu5Yh5Zd9hykraf?p=preview)を作成しました。ここで問題を引き起こしている可能性のあることはありますか? – nikaspran

+0

mmm面白いです。私はもっ​​と試してみるよ。おそらく2つのレベルのオブジェクトが原因です。 – WindowsMaker

+0

いいえ、あなたが正しいです、私は馬鹿です。あなたがそれを使用している方法は、プランカとは少し異なります。同様のユースケースをどのように扱うかについて、私はちょっと答えを書きます。 – nikaspran

答えて

1

私は前に非常に正常に使用しているそれはこの:

オプション#1から

「アップ」結合する1つの方法は、我々は、同じ工場の構造を持っていると仮定します

angular.module('someApp').factory('SomeFactory', function($http) { 
    var cache = {}; 

    $http({...some params...}) 
    .success(function(data) { 
     // ... 
     cache[key] = data; 
    }); 

    return { 
    cache: cache 
    }; 
}); 

代わりにitemsを設定します直接cache[key]であれば、工場自体にバインドすることができます。あなただけng-repeat="item in $ctrl.cache[key]"を使用して、それが自動的に最新の変更を取得するテンプレートに続いて

this.cache = SomeFactory.cache // bind to container which is going to persist 

:結局のところ、工場(またはサービス)は、単にオブジェクトです。余分な手順を踏んで、サービスをthis.SomeFactory = SomeFactoryのように直接スコープにバインドして、$ctrl.SomeFactory.cache[key]というビューで使用することもできます。これは、アプリケーションごとに1回読み込まれるデータ構造や、特定のコントローラ向けに特別に作成されたサービスに適しています。

このアプローチでは、使用方法によっては問題が発生する可能性があります。配列の変更については言及しましたが、参照を非同期的にオーバーライドするため、変更が確実に維持されるようにすることは困難です。

オプション#2 - これを解決する別の方法は、私たちの工場を少し変更することでそれを

を交換しないで、配列を変更:

angular.module('someApp').factory('SomeFactory', function($http) { 
    var cache = {}; 
    cache[key] = []; // initialise an array which we'll use everywhere 

    $http({...some params...}) 
    .success(function(data) { 
     // ... 
     cache[key].push.apply(cache[key], data); // essentially a pushAll 
     // we could also set cache[key].length = 0 to clear previous data or do something else entirely 
    }); 

    return { 
    cache: cache 
    }; 
}); 

あなたが見ることができるように、代わりの参照を置き換えますitemsプロパティが参照しているのと同じ配列で操作しています。ここでの利点は、配列を何らかの方法で操作する(つまり余分な項目を追加する)と、新しい非同期データを受け取った後の処理の柔軟性がさらに強化されることです。

これは、ngResourceが使用するアプローチと実際に似ています。コレクションクエリメソッドは、データが実際にフェッチされると、後で記入された配列を返します。

オプション#3 - 私は前に使ってきた最終的な方法は、単にデータのための約束を公開することです約束

を公開:

angular.module('someApp').factory('SomeFactory', function($http) { 
    var cache = {}; 

    var whenReady = $http({...some params...}) 
    .then(function(data) { 
     // ... 
     cache[key] = data; 
     return data; 
    }); 

    return { 
    cache: cache, 
    whenReady: whenReady 
    }; 
}); 

次にコントローラであなたは一度だけ、それを割り当てますそれが解決されます。

SomeFactory.whenReady.then(items => { 
    this.items = items; // or this.items = SomeFactory.cache[key]; 
}); 

は、これらのすべては、余分な$watchを避けるが、それはあなたのアプリケーションのための最も便利だかに依存します。

+0

素晴らしい答えに感謝します。オプション#2では、本質的にすべての要素をコピーすることによるパフォーマンスの影響は何ですか? – WindowsMaker

+0

要素をコピーしていないので、基本的にループ内で 'cache [key] .push'を呼び出すので、新しい配列を作成することさえできません。パフォーマンスへの影響については、プロファイルすることが最善の方法です。これは、あなたが非常に頻繁に行うことでない限り、重要ではないでしょう。私はどちらの解決策が最も保守的であるかを選択し、問題がある場合はプロファイリング後に決定するとします。 – nikaspran

関連する問題