原文連接 : Sharing Data Between Controllers? Best Practice: Use a Service
原文做者 : DAVE CEDDIA
譯者 : 李林璞(web前端領域)
譯者注:翻譯若有疏漏,歡迎指出!感謝!轉載請保留此頭部。前端
Angular開始起來簡單易用,甚至說神奇。「哇哦!雙向綁定!」git
你會火燒眉毛地去構建你的傑做,直到碰到釘子:你正在像網上每一個人建議的那樣去構建一個獨立的組件,但怎麼和其餘組件共享數據呢?github
或許你在不一樣的路由裏有兩個視圖都須要訪問某些狀態變量,又或者你有三個分離的組件須要訪問一樣的一堆數據。web
共享數據的最佳策略是什麼呢?用一些變態的控制器繼承方案嗎?數組
固然不是,最簡單容易的方式就是使用服務(service)。this
假設有兩個並排的面板,每一個面板表明一個指令(directive):spa
下面是面板1的代碼:翻譯
angular.directive('paneOne', function() { return { restrict: 'E', scope: {}, template: [ '<div>', '<input ng-model="p1.text">', '<button ng-click="p1.addToList()">Add To List</button>', '</div>' ].join(''), controllerAs: 'p1', controller: function() { var vm = this; vm.text = ""; vm.addToList = function() { // TODO: add to the list in Pane 2 somehow vm.text = ""; }; } }; });
面板2的:雙向綁定
angular.directive('paneTwo', function() { return { restrict: 'E', scope: {}, template: [ '<ul>', '<li ng-repeat="item in p2.listItems">{{ item }}</li>', '</ul>' ].join(''), controllerAs: 'p2', controller: function() { var vm = this; // TODO: get this list of items from Pane 1 somehow vm.listItems = []; } }; });
咱們想要實現的是在面板1的輸入框中輸入某些東西,而後點擊按鈕 「Add To List」, 這條內容就會在面板2的列表中出現。rest
爲了在兩個甚至更多的控制器間共享數據,建立一個服務去扮演中間件的角色。這樣可使控制器(或組件)保持鬆散耦合:它們不須要知道其餘的控制器(或組件)是怎麼樣的,它們只須要知道數據源 - 你建立的中間件服務。
angular.factory('sharedList', function() { var list = []; return { addItem: addItem, getList: getList }; function addItem(item) { list.push(item); } function getList() { return list; } });
上面這個服務很是簡單,調用 addItem
把數據放到列表裏,而後調用 getList
獲取整個列表。這真的很簡單,甚至不須要去移除或者清空列表項,看到這個方法的簡便之處了吧。
既然咱們已經建立好了咱們的服務,咱們就須要在任何須要訪問或修改數據的地方去注入它了。
先從面板1的控制器開始:
// Inject sharedList controller: function(sharedList) { var vm = this; vm.text = ""; vm.addToList = function() { // Stuff the item into the shared list sharedList.addItem(vm.text); vm.text = ""; }; }
而後是面板2的控制器,獲取數據:
// Inject sharedList controller: function(sharedList) { var vm = this; // Read the data vm.listItems = sharedList.getList(); }
從JSBin裏看看運行狀況。
當我寫到這兒的時候,我很是肯定面板2中的列表在我添加一些觀察器前不會自動更新 。
可是接下來當我把代碼放到 JSBin 裏的時候...你瞧,它居然能夠更新!爲何呢?
ng-repeat
給循環的數組設置了觀察器。
點擊 「Add To List」 觸發了一個消化週期 (digest cycle),它就會從新檢測 ng-repeat
的觀察器。
由於 sharedData.getList()
返回了一個數組的引用,觀察器就會看到 p2.listItems
已經發生了變化。這裏是關鍵:若是 getList
返回一個不一樣於由 addToList
更改的數組,這就不會觸發更新了。
因此:這種通訊方式能夠在沒有觀察器的狀況下完美運行。但若是你發現失敗了的話,檢查一下你是怎麼傳遞數據的,或許你須要明確地建立一個觀察器檢測變化。
建立一個服務去存放你的數據,並給數據建立 getter
和 setter
的方法。
在任何須要這個數據的地方注入這個服務。
這幾乎就是所有內容了(除非你須要觀察器 - 這種狀況下,你仍是添加一個吧)。
感謝閱讀!