欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解AngularJS的通信機制

 更新時間:2015年06月18日 11:27:41   投稿:goldensun  
這篇文章主要介紹了AngularJS的通信機制,AngularJS是非常具有人氣的JavaScript庫,需要的朋友可以參考下

現(xiàn)在幾乎滿世界的人都在問! 外面有人么? 這里是 USS AngularJS, 我們遇到麻煩了,我們的服務(wù)講得是克靈貢語(Klingon) 而我們的控制器不能同它們的Ferengi 指令通信了. 有人能幫助我們么!

我已經(jīng)不知道有多少次遇到這種有關(guān)什么才是AngularJS里面的組件通信的最佳方式這樣的問題了. 很多時候答案都會是為此使用 $rootScope 對象去向任何想要收聽的人廣播$broadcast出一條消息. 然而,那還真不是做這件事的最佳方式. 組件之間廣播消息意味著它們需要多少知道一些其它組件編碼的細(xì)節(jié),這樣就限制了它們的模塊化和重用.

本文我就將展示如何為AngularJS中的內(nèi)部組件通信使用發(fā)布/訂閱模式.


AngularJS 有多種方式可供你用于組件之間的通信,而最常使用的方法卻需要你知道太多有關(guān)那些組件如何通信的細(xì)節(jié),這樣就增加了組件之間的耦合度,并降低了它們的模塊性和內(nèi)聚程度. 這樣也就使得你的組件很難在其它應(yīng)用程序中重用.

通過使用發(fā)布/訂閱設(shè)計模式,我們可以降低組件之間的耦合度,并將它們的之間通信的細(xì)節(jié)封裝起來. 這將能幫助增加你組件的模塊化程度,可測試性以及可重用性.

我將會描述的發(fā)布/訂閱模式實現(xiàn)由 Eric Burley, @eburley 在它的帖子angularjs.org 觀察, 有關(guān)發(fā)布訂閱模式.. 中推薦過。

我所描述的示例應(yīng)用程序,會向你展示你可以將發(fā)布/訂閱模式如何運用于內(nèi)部控制器通信以及控制器的服務(wù)通信. 你可以在GitHub上我的資源庫 angularjs-pubsub 下面找到源代碼.
 
首先我們需要一條通信管道

首先我們來講講用于處理發(fā)布和訂閱信息的服務(wù)。我定義了一個服務(wù)接口,提供了發(fā)布和訂閱信息的方法,我們可以用它來處理我們想要用來交換的信息。

在下面的代碼中,我定義了兩個內(nèi)部信息; _EDIT_DATA_, 用來表示我們需要編輯跟隨信息傳過來的數(shù)據(jù),和 _DATA_UPDATED_, 用來表示我們的數(shù)據(jù)已經(jīng)被改變。這些都是定義在內(nèi)部的,用戶沒辦法訪問到它們的,這樣有助于隱藏具體實現(xiàn)。

而對于每條信息,有兩個方法; 一個用來發(fā)布信息推送給訂閱者,另一個可以讓訂閱者注冊一個回調(diào)方法,當(dāng)接收到信息的時候,這個方法就會被調(diào)用。


用來向訂閱者發(fā)布信息方法是 editData,在第 9 行,還有 dataUpated,在第 19 行。它們通過 $rootScope.$broadcast 方法向待處理事件推送私有通知。

用來注冊事件的方法,通過 $scope.$on 建立監(jiān)聽,當(dāng)接收到廣播的消息之后,就會輪流執(zhí)行那些被訂閱者注冊到服務(wù)上的事件。同時,由于訂閱者需要自己的 scope 作為參數(shù)傳過來,我們可以用它來執(zhí)行監(jiān)聽的信息,從而避免了維護監(jiān)聽者列表這些復(fù)雜的處理。注冊事件的方法是 onEditData,在 13 行,還有 onDataUpdated 在 23 行。

為了隱藏實現(xiàn)細(xì)節(jié),我用了 Revealing Module (揭示模塊:好丑的名字)模式,只返回那些我希望讓用戶使用的方法。
 

angular.module(['application.services'])
  // define the request notification channel for the pub/sub service
  .factory('requestNotificationChannel', ['$rootScope', function ($rootScope) {
    // private notification messages
    var _EDIT_DATA_ = '_EDIT_DATA_';
    var _DATA_UPDATED_ = '_DATA_UPDATED_';
 
    // publish edit data notification
    var editData = function (item) {
      $rootScope.$broadcast(_EDIT_DATA_, {item: item});
    };
    //subscribe to edit data notification
    var onEditData = function($scope, handler) {
      $scope.$on(_EDIT_DATA_, function(event, args) {
        handler(args.item);
      });
    };
    // publish data changed notification
    var dataUpdated = function () {
      $rootScope.$broadcast(_DATA_UPDATED_);
    };
    // subscribe to data changed notification
    var onDataUpdated = function ($scope, handler) {
      $scope.$on(_DATA_UPDATED_, function (event) {
        handler();
      });
    };
    // return the publicly accessible methods
    return {
      editData: editData,
      onEditData: onEditData,
      dataUpdated: dataUpdated,
      onDataUpdated: onDataUpdated
    };
  }])

發(fā)布消息

發(fā)布消息很簡單,首先我們需要在我們的控制器里為 requestNotificationChannel 引入一些依賴. 你可以在下面dataService的定義第二行看到這個. 當(dāng)事件發(fā)生時,如果需要向需要了解有變化發(fā)生的其它對象發(fā)送信號, 你只需要調(diào)用requestNotificationChannel上恰當(dāng)?shù)耐ㄖ椒ň涂梢粤? 如果你注意到了dataService的 saveHop, deleteHop 和 addHop 方法, 你就會看到它們都調(diào)用了 requestNotificationChannel 上的dataUpdated方法, 這個方法將會給偵聽器發(fā)送信號,偵聽器則已經(jīng)用 onDataUpdated 方法注冊過了.

  // define the data service that manages the data
  .factory('dataService', ['requestNotificationChannel', function (requestNotificationChannel) {
    // private data
    var hops = [
      { "_id": { "$oid": "50ae677361d118e3646d7d6c"}, "Name": "Admiral", "Origin": "United Kingdom", "Alpha": 14.75, "Amount": 0.0, "Use": "Boil", "Time": 0.0, "Notes": "Bittering hops derived from Wye Challenger. Good high-alpha bittering hops. Use for: Ales Aroma: Primarily for bittering Substitutions: Target, Northdown, Challenger", "Type": "Bittering", "Form": "Pellet", "Beta": 5.6, "HSI": 15.0, "Humulene": 0.0, "Caryophyllene": 0.0, "Cohumulone": 0.0, "Myrcene": 0.0, "Substitutes": ""} ,
      { "_id": { "$oid": "50ae677361d118e3646d7d6d"}, "Name": "Ahtanum", "Origin": "U.S.", "Alpha": 6.0, "Amount": 0.0, "Use": "Boil", "Time": 0.0, "Notes": "Distinctive aromatic hops with moderate bittering power from Washington. Use for: Distinctive aroma Substitutes: N/A", "Type": "Aroma", "Form": "Pellet", "Beta": 5.25, "HSI": 30.0, "Humulene": 0.0, "Caryophyllene": 0.0, "Cohumulone": 0.0, "Myrcene": 0.0, "Substitutes": ""} ,
      { "_id": { "$oid": "50ae677361d118e3646d7d6e"}, "Name": "Amarillo Gold", "Origin": "U.S.", "Alpha": 8.5, "Amount": 0.0, "Use": "Boil", "Time": 0.0, "Notes": "Unknown origin, but character similar to Cascade. Use for: IPAs, Ales Aroma: Citrus, Flowery Substitutions: Cascade, Centennial", "Type": "Aroma", "Form": "Pellet", "Beta": 6.0, "HSI": 25.0, "Humulene": 0.0, "Caryophyllene": 0.0, "Cohumulone": 0.0, "Myrcene": 0.0, "Substitutes": ""} ,
      { "_id": { "$oid": "50ae677361d118e3646d7d6f"}, "Name": "Aquila", "Origin": "U.S.", "Alpha": 6.5, "Amount": 0.0, "Use": "Boil", "Time": 0.0, "Notes": "Aroma hops developed in 1988. Limited use due to high cohumolone.Used for: Aroma hops Substitutes: ClusterNo longer commercially grown.", "Type": "Aroma", "Form": "Pellet", "Beta": 3.0, "HSI": 35.0, "Humulene": 0.0, "Caryophyllene": 0.0, "Cohumulone": 0.0, "Myrcene": 0.0, "Substitutes": ""} ,
      { "_id": { "$oid": "50ae677361d118e3646d7d70"}, "Name": "Auscha (Saaz)", "Origin": "Czech Republic", "Alpha": 3.3, "Amount": 0.0, "Use": "Boil", "Time": 0.0, "Notes": " Use for: Pilsners and Bohemian style lagers Aroma: Delicate, mild, clean, somewhat floral -- Noble hops Substitute: Tettnanger, LublinExamples: Pulsner Urquell", "Type": "Aroma", "Form": "Pellet", "Beta": 3.5, "HSI": 42.0, "Humulene": 0.0, "Caryophyllene": 0.0, "Cohumulone": 0.0, "Myrcene": 0.0, "Substitutes": ""} ,
    ];
    // sends notification that data has been updated
    var saveHop = function(hop) {
      requestNotificationChannel.dataUpdated();
    };
    // removes the item from the array and sends a notification that data has been updated
    var deleteHop = function(hop) {
      for(var i = 0; i < hops.length; i++) {
        if(hops[i]._id.$oid === hop._id.$oid) {
          hops.splice(i, 1);
          requestNotificationChannel.dataUpdated();
          return;
        }
      };
    };
    // internal function to generate a random number guid generation
    var S4 = function() {
      return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    };
    // generates a guid for adding items to array
    var guid = function () {
     return (S4() + S4() + "-" + S4() + "-4" + S4().substr(0,3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase();
    };
    // function to add a hop to the array and sends a notification that data has been updated
    var addHop = function(hop) {
      hops.id.$oid = guid();
      hops.push(hop);
      requestNotificationChannel.dataUpdated();
    };
    // returns the array of hops
    var getHops = function() {
      return hops;
    };
    // returns a specific hop with the given id
    var getHop = function(id) {
      for(var i = 0; i < hops.length; i++) {
        if(hops[i]._id.$oid === id) {
          return hops[i];
        }
      };
    };
    // return the publicly accessible methods
    return {
      getHops: getHops,
      getHop: getHop,
      saveHop: saveHop,
      deleteHop: deleteHop,
      addHop: addHop
    }
  }]);

 
接收事件通知

從 requestNotificationChannel 接收事件通知也很簡單,額外的我們只需要回調(diào)處理器來在消息被發(fā)送時使用通知來做一些自己的處理. 我們將再次需要添加一些依賴到面向我們的控制器、服務(wù)以及指令的 requestNotificationChannel 上, 你可以在下面代碼的第二行中看到這些. 接下來我們需要定義一個事件回調(diào)處理器來對事件通知做出回應(yīng),你可以在下面的第五行代碼中看到. 然后我們需要通過調(diào)用 onDataUpdated 方法來吧我們的回調(diào)處理器注冊到requestNotificationChannel,并傳入來自控制器和回調(diào)處理器的范圍, 我們在第9行代碼中做了這些事情.

 

  //define the controller for view1
  .controller('view1-controller', ['$scope', 'dataService', 'requestNotificationChannel', function($scope, dataService, requestNotificationChannel) {
    $scope.hops = dataService.getHops();
 
    var onDataUpdatedHandler = function() {
      $scope.hops = dataService.getHops();
    }
 
    requestNotificationChannel.onDataUpdated($scope, onDataUpdatedHandler);
 
    $scope.onEdit = function(hop) {
      requestNotificationChannel.editData(hop);
    }
 
    $scope.onDelete = function(hop) {
      dataService.deleteHop(hop);
    }
  }]);

用于控制器通信的控制器

我們也可以將 the requestNotificationChannel 用于控制器間的通信. 我們只需要有一個控制器扮演發(fā)布者的角色,而另外一個控制器扮演訂閱者的角色就行了. 如果你觀察到前段代碼第11行view1-controller的onEdit方法,你會看到它發(fā)送了一個editData消息,消息包含需要使用 requestNotificationChannel 編輯的項.  下面的 view2-controller 從第5行到第9行將它的 onEditDataHandler 用 requestNotificationChannel 進行了注冊. 如此無論何時view1-controller一旦發(fā)送editData消息,帶上要修改的項,view2-controller都會受到editData消息的通知,獲得該項并將其更新到它的模型.
 

  //define the controller for view1
  .controller('view2-controller', ['$scope', 'dataService', 'requestNotificationChannel', function($scope, dataService, requestNotificationChannel) {
    $scope.hop = null;
 
    var onEditDataHandler = function(item) {
      $scope.hop = item;
    };
 
    requestNotificationChannel.onEditData($scope, onEditDataHandler);
 
    $scope.onSave = function() {
      dataService.saveHop($scope.hop);
      $scope.hop = null;
    }
 
    $scope.onCancel = function() {
      $scope.hop = null;
    }
  }]);

寫一個好的接口文檔

有一件事情可能會被忽略,我們在組件間用了通信接口,而這些接口,它們需要一個好的文檔來說明應(yīng)當(dāng)如何使用。上面的例子中,如果沒有文檔,用戶肯定不會知道 onEditData 會給回調(diào)函數(shù)傳一個待編輯數(shù)據(jù)。所以當(dāng)你開始用這個模式,用好的技巧在于,給方法寫注釋文檔,以確保通知服務(wù)明確知道發(fā)生了什么事情。
總結(jié)

好了,我們探討了如何在你的 AngularJS 應(yīng)用中使用訂閱/發(fā)布模式來實現(xiàn)模塊間通信。該模式可以讓你的模塊從內(nèi)部消息解耦,更便于復(fù)用。你甚至可以把模塊之間的通信全部替換成訂閱/發(fā)布模式。尤其當(dāng)你的服務(wù)中有很多異步請求,以及你希望把數(shù)據(jù)緩存在服務(wù)中,從而減少和服務(wù)器通信的時候,這種模式相當(dāng)有效。

我希望這對你有所幫助,你可以在我的 GitHub 倉庫 angularjs-pubsub 下找到例子的代碼。

相關(guān)文章

  • Angular4學(xué)習(xí)筆記之準(zhǔn)備和環(huán)境搭建項目

    Angular4學(xué)習(xí)筆記之準(zhǔn)備和環(huán)境搭建項目

    這篇文章主要介紹了Angular4學(xué)習(xí)筆記之準(zhǔn)備和環(huán)境搭建項目,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • 利用Angular2 + Ionic3開發(fā)IOS應(yīng)用實例教程

    利用Angular2 + Ionic3開發(fā)IOS應(yīng)用實例教程

    這篇文章主要給大家介紹了關(guān)于利用Angular2 + Ionic3開發(fā)IOS應(yīng)用的相關(guān)資料,文中通過示例代碼和圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • AngularJS使用ngOption實現(xiàn)下拉列表的實例代碼

    AngularJS使用ngOption實現(xiàn)下拉列表的實例代碼

    這篇文章主要介紹了AngularJS使用ngOption實現(xiàn)下拉列表的實例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • AngularJS ng-bind-html 指令詳解及實例代碼

    AngularJS ng-bind-html 指令詳解及實例代碼

    本文主要是對AngularJS ng-bind-html 指令知識的詳細(xì)講解,并附代碼實例,有需要的小伙伴可以參考下
    2016-07-07
  • Angular.Js中過濾器filter與自定義過濾器filter實例詳解

    Angular.Js中過濾器filter與自定義過濾器filter實例詳解

    Angularjs過濾器是 angularjs非常棒的特性之一。有朝一日,你可能需要使用自定義過濾器,所以下面這篇文章主要給大家介紹了Angular.Js中過濾器filter與自定義過濾器filter的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • AngularJS實現(xiàn)表單驗證

    AngularJS實現(xiàn)表單驗證

    客戶端表單驗證是AngularJS里面最酷的功能之一。 AngularJS表單驗證可以讓你從一開始就寫出一個具有交互性和可相應(yīng)的現(xiàn)代HTML5表單。在AngularJS中,有許多表單驗證指令。在這里,我們將談?wù)剮讉€最流行指令,然后我們將討論如何編寫自定義的驗證。
    2015-01-01
  • 詳解AngularJS 過濾器的使用

    詳解AngularJS 過濾器的使用

    AngularJS 過濾器可用于轉(zhuǎn)換數(shù)據(jù),這篇文章主要介紹了詳解AngularJS 過濾器的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • AngularJS的一些基本樣式初窺

    AngularJS的一些基本樣式初窺

    這篇文章主要介紹了AngularJS的一些基本樣式初窺,AngularJS是一款高人氣JavaScript框架,需要的朋友可以參考下
    2015-07-07
  • Angular4 Select選擇改變事件的方法

    Angular4 Select選擇改變事件的方法

    今天小編就為大家分享一篇Angular4 Select選擇改變事件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Angular2使用Angular-CLI快速搭建工程(二)

    Angular2使用Angular-CLI快速搭建工程(二)

    這篇文章主要介紹了Angular2使用Angular-CLI快速搭建工程(二),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評論