AngularJs中,如何在父元素中調用子元素為自定義Directive中定義的函數?


 最近一段時間准備使用AngularJs中的自定義Directive重構一下代碼。

在這里說明一下,把自定義控件封裝成Directive並不一定是要復用,而是要讓代碼結構更加清晰。就好像你將一個長方法拆分成多個獨立的小方法,也未必要復用它們一樣。職責獨立等一票好處,會讓后期維護更加輕松。

在重構的過程中,我遇到了這樣一個問題,先上圖:

圖一:

這就是我要重構的界面,由於之前時間緊,將這三個Filter和兩個button都寫在了一個頁面中。當時我已經預感到,如果將這里面的狀態都寫到一個scope上,將出現后期近乎不可維護的災難。盡管我已經將它們用ViewModel隔離,但代碼結構依然讓我很不滿意。

你說啥?沒看出來哪復雜。好,你等着,接下來讓你看看里面啥樣。

 

圖二:

這是其中一個下拉框展開的模樣。什么?你覺得這很一般吶?沒看出它多么猙獰?好,你等着。上圖三。

 

圖三:

這是三哥展開之后的完全體。現在你應該明白將它們封裝成directive是多么必要。

(上圖中的這個產品是如今風靡全球的DocAveOnline,使用微軟SharePoint的公司沒有不知道的。啥?你沒聽過?偶,忘了說了,只有大公司才用得上)

我重構的思路很簡單,將每一個下拉框都獨立寫成一個directive,然后將哥仨嵌入同一個Directive中,這個外層的directive里面包含Filter和Reset兩個Button。

這里原本的交互邏輯是這樣的,每個下拉框中的元素都有自己的初始化狀態。但是不論你之前怎么霍霍,點擊那個Reset按鈕之后,要恢復每個下拉框的“出廠設置”。

每個下拉框的Directive擁有獨立的scope是肯定的,一切自給自足,與外界無關。也就是說,每個下拉框的reset方法是封裝在自己的Directive之中。

那么問題來了,我點擊Reset按鈕之后,怎么才能調用其子元素中的reset方法?

開始我嘗試使用require和link的組合,我是想將reset方法封裝到下拉框的controller中,然后在父元素中將三個下拉框對應的directive名字寫到require中,這樣我就能在父元素的link方法的第四個參數中取到,由這三個子元素controller組成的數組,這我就能輕松調用每個controller的reset方法。(本來controller的作用就是對外暴露API)

可寫着寫着我就發現不對,好像require只能找自己或者向父元素查找,沒法由父元素發起向子元素查找的行動。(也許有,但沒找到。如果你知道請在留言中告訴我。)

在江郎才盡的情況下,請教了我師父,他告訴我以下這種方法,其實一點兒都不難,就看你是否理解了自定義directive中,scope里面的,'='這個符號。

稍微懂點兒就知道,這是雙向綁定的意思。那解決辦法來了,代碼如下:

Html部分:

<div ng-controller="myCtrl">
    <div>
        <inner-directive filter-model="filterModel"></inner-directive>
        <button ng-click="filterModel.reset()">click</button>
    </div>
</div>

Js部分:

 <script>
  angular.module('app',[])
     .controller('myCtrl',function($scope){
         $scope.filterModel = {
             name:'xiaomablog'
           };
    })
       .directive('innerDirective',function(){
         return {
            restrict:'E',
             scope:{
               filterModel:'='
             },
             template:'<div ng-bind="filterModel.name"></div>',
             link:function(scope,elem,attrs){
               scope.filterModel.reset = function(){
                  console.log('reset');
                 };
             }
        }
   });
</script>

在innerDirective中的scope屬性中,定義了filterModel這個雙向綁定的屬性,這就意味着directive內部可以霍霍這個屬性,外部myCtrl中也可以霍霍這個屬性,這樣的話彼此都能調用對方霍霍的結果。

我貼心地下了斷點,debug給你看:

第一步:

Angular的啟動過程是先初始化外部的scope,也就是先執行myCtrl中的方法,給filterModel賦了一個對象;

(注意,此刻filterModel的值為undefined)

 

第二步:

 

(沒添加reset方法之前,已經看到了之前加的name屬性)

然后才執行directive的link方法,將scope與DOM緊緊地聯系在一起。

 

 第三步:

此時點擊button,已經能調用reset方法了,並在console中打印出'reset'

大家可以嘗試在myCtrl和innerDirective的link方法中加斷點debug一下,親自觀察執行順序,加深印象。

注意:

      我們了解錘子的方式 , 不是盯着它看 , 而是拿起來用。

                  —— 馬丁·海德格爾

聽馬丁的話,趕緊去敲。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM