2013-03-07 6 views
1

나는 한 가지 질문에 어려움을 겪고 있으며 왜 그런 일이 일어나는지 알 수 없다.Angularjs의 지시문은 어떻게 작동합니까?

모듈 (portfolioModule), 서비스 (Menu) 및 지시문 (niMenu)이 있습니다. 지시문은 하위 항목이있는 메뉴 항목을 렌더링해야합니다.

HTML :

<div ng-app="portfolioModule"> 
    <script id="menuItem" type="text/ng-template"> 
    <li> 
     <a>{{item.name}}</a> 
     <ul> 
      <li ng-repeat="item in menu.getKids(item.id)" ng-include="'menuItem'"></li> 
     </ul> 
    </li> 
    </script> 

    <div> 
     <div ni-menu="test">test1</div> 
    </div> 
</div> 

자바 스크립트 :

var portfolioModule = angular.module('portfolioModule', []); 

portfolioModule.factory('Menu', function() { 
     var items = [ 
      { 
       "parent_id": null, 
       "id": 1, 
       "name": "foo" 
      }, { 
       "parent_id": 1, 
       "id": 2, 
       "name": "foo-bar" 
      } 
     ]; 
     this.getKids = function(parent_id) { 
      var result = []; 
      parent_id = parent_id || null; 

      console.log('getKids', parent_id); 
      angular.forEach(items, function(value) { 
       if (value.parent_id === parent_id) { 
        result.push(value); 
       } 
      }); 
      return result; 
     }; 

     return this; 
    } 
); 

portfolioModule.directive('niMenu', function(Menu) { 
     var niMenu; 
     return niMenu = { 
      template: '<ul ng-include="\'menuItem\'" ng-repeat="item in menu.getKids()"></ul>', 
      restirt: 'A', 
      link: function(scope, element, attrs) { 
       console.log('link'); 
       scope.menu = Menu; 
      } 
     }; 
    } 
); 

근무 데모 : http://jsfiddle.net/VanSanblch/Ng7ef.

html에서는 ni-menu를 ni-menu로 호출합니다. 지시어는 Menu-service를 모듈의 범위에 넣는 템플릿과 링크 함수를 가지고있다. 지시문의 템플릿에서 Menu.getKids()를 사용하고 모든 최상위 항목을 가져옵니다. 나중에 ng-include가 사용하는 템플릿에서 Menu.getKids (item.id)를 호출하고 특정 항목의 모든 하위 항목을 가져옵니다.

작은 세부 사항 하나만 제외하면 모든 것이 훌륭하게 작동합니다. 콘솔을 열면 예상보다 많은 getKids 호출이 있음을 알 수 있습니다. 예를 들어, 두 요소의 배열의 경우 getKids 호출 수가 9입니다.

누군가 지구상에서 왜 그런지 설명 할 수 있습니까?

+1

죄송합니다 - 피들 링크를 끊었습니다. :-) –

+1

@JoshDavidMiller가 수정되었습니다. –

답변

6

좋아요, 그것이 두 번 이상 실행되는 이유는 다이제스트주기가 작동하는 방식이기 때문입니다. 아무런 변화가 없을 때까지 모든보기 표현식 (예 : ngRepeat에 전달한 표현식)을 계속 실행합니다. 자세한 내용은 this answer을 참조하십시오. 테이크 어웨이는 다음과 같습니다. 을 적어도 한 번 이상 번 이상 실행하지만 그보다 더 자주 실행합니다.

ngRepeat를 사용하는 경우 일반적으로 성능에 부정적인 영향을주기 때문에 함수에서 데이터를 가져 오지 않으려합니다. 왜 데이터가 변경되지 않았을 때 같은 함수를 두 번 이상 호출해야합니까? 더 나은 방법은 컨트롤러 (또는이 경우에는 지시자)가 함수를 실행하고 스코프에 결과를 저장하는 것입니다. 따라서 ngRepeat는 ng-repeat="item in getItems()" 대신 ng-repeat="item in items"처럼 보입니다.

불행하게도, 그것은 당신이 지시어를 작동시키는 방식을 재구성해야한다는 것을 의미합니다. 당신의 지시어를 조금 더 간단하게 다시 작성할 수 있기 때문에 이것은 좋은 생각입니다. 예를 들어 ngInclude는 필요 없습니다.

전체 메뉴를 나타내는 템플릿과 하위 항목을 나타내는 템플릿 (두 번째 템플릿은 하위 항목을 가질 수 있음)이 있으므로 두 가지 지시문을 만듭니다. menu 지시문은 최상위 메뉴 항목을 반복해야하며 각 항목에 대해 menuItem을 그립니다. menuItem 지시문은 어린이를 확인하고 필요한 경우 더 많은 숫자로 menuItem 초 이상 반복해야합니다. 다음은 재귀 디렉토리를 수행하는 방법을 Andy Joslin이 만든 예제입니다 : http://plnkr.co/edit/T0BgQR.

이와 비슷한 것을 구현하려면이 질문의 범위를 벗어나지 만 도움이 필요하면 새로운 질문을 게시하십시오.

행운을 빈다.

+0

굉장! 그게 분명히 모든 것을 분명히합니다. 답변 주셔서 감사합니다. – vansanblch

+0

훌륭한 지침! 플 런커에서 예제를 사용하고자하는 사람에게만 알려주십시오.minifier와 uglifiers를 사용할 때 문제를 피하기 위해 'choiceDirective'를 긴 손으로 정의하는 것이 좋습니다. 따라서 app.directive ('choice', function ($ compile))는 app.directive ('choice', [ '$ compile', function ($ compile)'를 사용하십시오. 지시어 (directive) 메소드의 마지막에 닫는']'을 추가하십시오. –

관련 문제