2015-05-14 130 views
3

關於控制器之間的共享狀態。我很難找到權利的方式來解決SO上推薦的所有可能的解決方案。我用這個草圖來說明我到目前爲止使用工廠的基本想法。控制器之間的共享狀態 - angularjs

有工廠myFactory,它擁有一個共享變量sharedVar

控制器Ctrl1, Ctrl2, Ctrl3想要始終訪問更新版本。他們也可以致電updateViaHttp

factory-controller-communication

  1. 那是一個工廠權目的是什麼? (一般的共享狀態, 具體到像服務提供商和其他選項)

  2. 如果是這樣,腕錶以適當的方式如何改變sharedVar? (由 參考對象,$手錶,事件(廣播,上),...)

  3. 是否有行之有效爲對象,數組和 元一個一般模式

回答

1
  1. 你有正確的基本理念,以「工廠」你的意思是「服務」假設 - 它是一種混亂的,我知道,因爲服務是使用工廠函數聲明。也就是說,這是一個重要的區別,以便您可以更輕鬆地查找文檔等。

  2. 通過使用對象引用和注意watch depths in Angular(我的首選方法)或通過顯式註冊$觀看報表(仍然要小心觀看深度)。一般來說,我認爲你不應該濫用廣播,因爲它會讓你的代碼變得有點混亂。在這種情況下,它也有點違背服務的要點,這是共享狀態的來源。

  3. 我創建服務的一般模式是將我想使用的所有東西都綁定到對象(數據和函數),然後在工廠函數中返回該對象。有時你必須引入一些額外的嵌套,以便Javascript原型繼承不會與你混淆(再次參見手錶的深度),但這是一般想法。

爲您建立一個例子服務:

angular.factory('shareAndUpdate', ['dependencyInjection', function(dependency) { 
    var srvc = {}; 
    srvc.sharedVar = 'something'; 
    srvc.updateViaHttp = function(){ something }; 
    return srvc; 
}]); 
+0

您給出的示例似乎只要updateViaHttp不返回對象就會工作。如果是這樣,我分配srvc.sharedVar = returnedObj它包含參考。真的嗎? – Stefan

+0

你完全可以在服務中嵌套對象,唯一的竅門是你必須小心你如何看待這個值。我在那裏關於監視深度的鏈接更多地討論了這個問題,但基本上,當您更改屬性而不是對象時,可能會遇到問題,因爲該對象不會將自己標記爲「已更改」。同樣,您必須小心如何觀看服務的屬性,請參閱:http://stsc3000.github.io/blog/2013/10/26/a-tale-of-frankenstein-and-binding-to-service -values-in-angular-dot-js/Services只是你的整個應用程序使用的單例對象 –

+0

無法讓它工作,它改變了視圖工廠狀態丟失。其不持久 – Stefan

1

您可能正在尋找的東西像一個發佈訂閱服務:

https://www.npmjs.com/package/angular-pubsub

但是,以我的經驗,通過適當的設計,可以最大限度地減少必要的非嵌套控制器之間共享數據。

雖然有時它是不可避免的,但對於像登錄憑據,權限,東西等全是應用程序的東西。在這種情況下,您可以使用服務來確實共享/獲取控制器之間的狀態,或者您可以使用完整的pubsub機制。

  1. 工廠只是指定服務的另一種方式。工廠在被調用時會提供一個服務實例。這項服務可以用於你想要的任何事情,其中​​之一就是在你的控制器之間共享狀態。

  2. 您可以通過多種方式觀察共享變量,最簡單的就是繼承範圍,但正如您所提到的,有時您的控制器不一定會繼承它們的範圍。然後,您可以使用pubsub服務或僅在兩個控制器的共享作用域上廣播事件(例如$ rootScope,它是您應用程序的所有控制器範圍的父級)。

  3. 如果您要使用現有的pubsubservice,它仍然取決於您的實施控制器,以實際執行訂閱並觀察特定變量並相應地更新其相應的範圍。但是,如果您設計的應用程序的方式使您的控制器從共享作用域繼承變量,則可以避免這種情況。然後他們會使用正常的角度機制自動更新他們的東西。不幸的是,這並不總是能夠實現的,然後你所要做的就是實現一個pubsub服務。

1

工廠VS服務提供商VS - 唯一的差異是與依賴注入如何爲他們提供的情況給你。服務是專門爲提供單例而設計的,但它們只是添加單例特定功能的工廠的包裝。沒有什麼能阻止你從工廠返回一個單身人士。

使用服務共享狀態 - 你需要一個單身人士和一個服務使定義和注入單身人士變得容易。

SomeService: 
    var foo = { 
     bar = 'a'; 
    }; 
    function getFoo() { 
     return foo; 
    } 

SomeController[SomeService injected here] : 
    $scope.foo = SomeService.getFoo(); 
    $scope.$watch('foo.bar', ...); 
    $scope.setFooBar = function(val) { 
     $scope.foo.bar = val; 
    }; 

<a href="" ng-click="setFooBar('2')">2</a> 

這裏的一般模式是永遠做一個 $scope.foo = { bar: 'Some other reference' };因爲再視SomeService所有其他事情會得到,當你覆蓋它的新的參考 - 在「臭名昭著」 always use a "dot" in $scope stuff issue

相關問題