링크 vs 컴파일 vs 컨트롤러


529

지시문을 만들 때 컴파일러, 링크 함수 또는 컨트롤러에 코드를 넣을 수 있습니다.

문서에서 그들은 다음과 같이 설명합니다.

  • 컴파일 및 링크 함수는 각주기의 다른 단계에서 사용됩니다
  • 컨트롤러는 지시문간에 공유됩니다

그러나 나를 위해 어떤 종류의 코드가 어디로 가야할지 명확하지 않습니다.

예 : 컴파일에서 함수를 만들어 링크의 범위에 연결하거나 컨트롤러의 범위에 기능 만 연결할 수 있습니까?

각 지시문에 자체 제어기가있는 경우 지시문간에 제어기를 공유하는 방법은 무엇입니까? 컨트롤러가 실제로 공유됩니까 아니면 범위 속성입니까?



지시어 함수에 대한보다 포괄적 인 개요 : 각도 지시어-컴파일, 컨트롤러, 사전 링크 및 사후 링크 사용시기 .
Izhaki

1
지시어의 수명주기 다이어그램 (작성 단계)이있는 게시물을 작성했습니다. 아마 그것은 누군가를 도울 것입니다 : filimanjaro.com/2014/…
평균 Joe

답변:


470

컴파일 :

이것은 Angular가 실제로 지시문을 컴파일하는 단계입니다. 이 컴파일 함수는 주어진 지시문에 대한 각 참조에 대해 한 번만 호출됩니다. 예를 들어 ng-repeat 지시문을 사용한다고 가정하십시오. ng-repeat는 첨부 된 요소를 찾아서 첨부 된 html 조각을 추출하여 템플릿 함수를 만들어야합니다.

HandleBars, 밑줄 템플릿 또는 이와 동등한 것을 사용하는 경우 템플릿 함수를 추출하기 위해 템플릿을 컴파일하는 것과 같습니다. 이 템플릿 함수에 데이터를 전달하면 해당 함수의 반환 값이 올바른 위치에 데이터가있는 html입니다.

컴파일 단계는 템플릿 함수를 반환하는 Angular의 단계입니다. 이 템플릿 함수를 각도로 연결 함수라고합니다.

연결 단계 :

연결 단계는 데이터 ($ scope)를 연결 함수에 연결하는 위치이며 연결된 html을 반환해야합니다. 지시문은이 HTML의 위치 또는 변경 사항을 지정하므로 이미 사용하는 것이 좋습니다. 이것은 연결된 html, 즉 이미 데이터가 첨부 된 html을 변경하려는 기능입니다. 연결 함수에서 코드를 작성하면 일반적으로 사후 링크 기능 (기본적으로)으로 각도로 표시됩니다. 연결 함수가 데이터를 템플릿과 연결 한 후에 호출되는 콜백입니다.

컨트롤러 :

컨트롤러는 지시문 특정 로직을 넣는 곳입니다. 이 논리는 연결 기능으로도 들어갈 수 있지만, 그 논리를 "공유 가능"하게하려면 해당 논리를 범위에 두어야합니다. 그 문제는 실제로 예상하지 않은 지시문으로 범위를 손상시킬 수 있다는 것입니다. 두 지시어가 서로 대화하고 서로 협력하고 싶다면 대안은 무엇입니까? 물론 모든 논리를 서비스에 넣은 다음 이러한 지시문을 해당 서비스에 의존하게 만들 수 있지만 하나의 의존성을 더 가져올 수 있습니다. 대안은이 범위에 대한 컨트롤러를 제공하는 것 (보통 범위?)을 지정하고 해당 지시어가 다른 지시어를 "필요할 때"다른 지시어에 삽입합니다.


67
명확히하기 위해 : compile은 페이지 전체에서 사용될 템플릿을 컴파일합니다. 링커는 각 인스턴스에 연결됩니다. 권리? 그런 다음 컨트롤러는 인스턴스간에 작동합니다.
Zlatko

4
각 지시문 controller함수에 대한 @CMCDragonkai 는 컴파일 , 그러나 로컬 DOM 트리 분기 전에 실행 pre-link됩니다. 또한 controllerpre-link기능은 로컬에서 DOM 분기 이송 실행 하향식 방식. 그 후 상향식으로post-link 실행됩니다 .
Artem Platonov

9
이해하지 못하면 엉망입니다. 그것이하는 일을하는 이유가 있습니다.
demisx

3
이것은 올바른 기술 답변이지만 링크 기능을 사용해야 할 때 질문이 남아 있습니다.
Nicholas Marshall

2
우리 controllerlink어디에나 대신 사용할까요 ? 따라서 메소드를 공유해야하거나 논리를 도입 해야하는 경우 나중에 코드를 변경할 필요가 없습니다. controller링크 대신 항상 사용 하는 데 문제가 있습니까?
JPS

99

Google 팀의 O'Reily AngularJS 책에 다음과 같은 내용도 추가하고 싶었습니다.

컨트롤러-지시문 간 통신을위한 API를 게시하는 컨트롤러를 만듭니다. 좋은 예는 Directive to Directive Communication입니다.

링크-결과적으로 DOM 요소 인스턴스를 프로그래밍 방식으로 수정하고 이벤트 리스너를 추가하며 데이터 바인딩을 설정합니다.

컴파일-ng-repeat에서 사용될 때 지시문 사본 전체의 기능에 대해 DOM 템플릿을 프로그래밍 방식으로 수정합니다. 컴파일 함수는 링크 요소를 반환하여 결과 요소 인스턴스를 수정할 수도 있습니다.


지불하지 않으면 thinkster.io 링크를 볼 수 없습니다. 내 링크는 아니지만 아마도 더 적합합니다 : toddmotto.com/directive-to-directive-communication-with-require
R. van Twisk

51

A를 directive사용하면 웹 구성 요소를 작성하기 위해 HTML 어휘를 선언적 방식으로 확장 할 수 있습니다. 이 ng-app속성은 지시문이므로 ng-controller모든 ng- prefixed attributes. 지침이 될 수 있습니다 attributes, tags심지어 나 class names, comments.

지시문이 생성되는 방법 ( compilationinstantiation)

컴파일 : 우리는 compile함수가 manipulate렌더링되기 전에 DOM 을 사용하고 함수를 반환 할 link것입니다 (우리를 위해 링크를 처리 할 것입니다). 또한 instances이 지시문의 모든 부분과 공유해야하는 모든 메소드를 배치 할 수 있습니다 .

link :link함수를 사용하여 템플릿에서 복제 된 특정 DOM 요소에 모든 리스너를 등록하고 페이지에 대한 바인딩을 설정합니다.

에서 설정하면 compile()기능들은은 (당신이 원하는 것을 종종있는) 한 번 설정 한 것입니다. link()함수 에서 설정하면 HTML 요소가 객체의 데이터에 바인딩 될 때마다 설정됩니다 .

<div ng-repeat="i in [0,1,2]">
    <simple>
        <div>Inner content</div>
    </simple>
</div>

app.directive("simple", function(){
   return {
     restrict: "EA",
     transclude:true,
     template:"<div>{{label}}<div ng-transclude></div></div>",        
     compile: function(element, attributes){  
     return {
             pre: function(scope, element, attributes, controller, transcludeFn){

             },
             post: function(scope, element, attributes, controller, transcludeFn){

             }
         }
     },
     controller: function($scope){

     }
   };
});

Compile함수는 preand post링크 함수를 반환합니다 . 사전 링크 함수에는 인스턴스 템플릿과의 범위가 controller있지만 템플릿은 범위에 바인딩되지 않았으며 여전히 포함 된 내용이 없습니다.

Postlink function은 post link가 마지막으로 실행되는 함수입니다. 지금은 transclusion완전하다 the template is linked to a scope, 그리고 view will update with data bound values after the next digest cycle. 이 link옵션은 post-link기능 설정 바로 가기 입니다.

controller : 지시어 컨트롤러는 다른 지시어 연결 / 컴파일 단계로 전달 될 수 있습니다. 인터-디렉티브 커뮤니케이션에 사용하기위한 수단으로 다른 디렉티브에 주입 될 수 있습니다.

필요한 지시문의 이름을 지정해야합니다. 동일한 지시문 또는 해당 부모에 바인드되어야합니다. 이름 앞에 접두사를 붙일 수 있습니다 :

?  Will not raise any error if a mentioned directive does not exist.
^  Will look for the directive on parent elements, if not available on the same element.

대괄호 [‘directive1′, ‘directive2′, ‘directive3′]를 사용 하여 다중 지시문 컨트롤러가 필요합니다.

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

app.controller('MainCtrl', function($scope, $element) {
});

app.directive('parentDirective', function() {
  return {
    restrict: 'E',
    template: '<child-directive></child-directive>',
    controller: function($scope, $element){
      this.variable = "Hi Vinothbabu"
    }
  }
});

app.directive('childDirective', function() {
  return {
    restrict:  'E',
    template: '<h1>I am child</h1>',
    replace: true,
    require: '^parentDirective',
    link: function($scope, $element, attr, parentDirectCtrl){
      //you now have access to parentDirectCtrl.variable
    }
  }
});

1
parentDirectiveCtrl을 자식 컨트롤러로 가져 오는 방법을 보여주었습니다 ...이 예제 자식에는 컨트롤러가 없지만 링크 기능이 있습니다 ... 현재이 문제에 얽매이지 않아서 그렇지 않을 수도 있습니다 매우 중요하지만 흥미로운 질문입니다.
alockwood05

13

또한 컨트롤러 대 링크 기능을 사용하는 좋은 이유는 (범위, 요소 및 attr에 모두 액세스 할 수 있기 때문에) 사용 가능한 서비스 또는 종속성을 컨트롤러로 (및 순서대로) 전달할 수 있기 때문입니다. 링크 기능으로는 그렇게 할 수 없습니다. 다른 서명을 확인하십시오.

controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...

vs.

link: function(scope, element, attrs) {... //no services allowed

2
답을 내려 보낼 때 요점을 설명하기 위해 의견을 남겨주십시오. 감사합니다
svassr

53
나는 downvoter가 아니었지만 지시문 자체에 필요한 의존성을 여전히 주입 할 수 있기 때문에 이것은 정확하지 않습니다 module.directive('myDirective', function($window) { etc.... 그런 다음 링크 기능 내부에서 액세스 할 수 있습니다.
Mike Chamberlain

1
링크 기능에 서비스를 주입 할 수 있기 때문에 이것은 매우 잘못된 것 같습니다
Code Whisperer

1
@JoshRibakoff 최종 결과는 동일합니다. 링크 기능에서 서비스에 액세스 할 수 있습니다. 함수의 인수로 선언되는지 여부는 중요하지 않습니다. 이와 관련하여 Mike Chamberlain은 정확합니다
Cony Wyatt

1
@ cwyatt1 어구를 수정하고 있었는데, plnkr은 Angular의 기능이 아니기 때문에 link () 함수에 주입하는 것을 보여주지 않습니다. 내가 현혹 적이라고 생각할 수도 있지만 metamatts 의견은 이미 플런저가하는 것과 컨트롤러에 주입하는 것의 많은 중요한 차이점을 간략하게 설명합니다. OP는 차이점이 무엇인지 묻고 있으며 차이점이 있습니다.
조쉬 리바 코프

10

이것은 지시문 단계를 이해하기에 좋은 샘플입니다. http://codepen.io/anon/pen/oXMdBQ?editors=101

var app = angular.module('myapp', [])

app.directive('slngStylePrelink', function() {
    return {
        scope: {
            drctvName: '@'
        },
        controller: function($scope) {
            console.log('controller for ', $scope.drctvName);
        },
        compile: function(element, attr) {
            console.log("compile for ", attr.name)
            return {
                post: function($scope, element, attr) {
                    console.log('post link for ', attr.name)
                },
                pre: function($scope, element, attr) {
                    $scope.element = element;
                    console.log('pre link for ', attr.name)
                        // from angular.js 1.4.1
                    function ngStyleWatchAction(newStyles, oldStyles) {
                        if (oldStyles && (newStyles !== oldStyles)) {
                            forEach(oldStyles, function(val, style) {
                                element.css(style, '');
                            });
                        }
                        if (newStyles) element.css(newStyles);
                    }

                    $scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);

                    // Run immediately, because the watcher's first run is async
                    ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
                }
            };
        }
    };
});

html

<body ng-app="myapp">
    <div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
        <div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
        </div>
    </div>
</body>

4
이 샘플 코드의 차이를 이해하는 데 도움이 될 것이다 당신은 왜에 정교한 수 link, compile그리고 controller?
cel sharp

required 지시문을 종속 지시문의 컨트롤러에 삽입 하는 방법을 알고 있습니까?
alockwood05

코드 펜 예제 : 캐치되지 않은 오류 : [$ injector : modulerr] 다음으로 인해 모듈 myapp를 인스턴스화하지 못했습니다 : 오류 : [$ injector : unpr] 알 수없는 제공자 : slngStylePrelinkProvider
rofrol

7
  • 엮다 : 새 표현식 추가,이 지시문 안에 다른 지시문 추가와 같은 지시문 템플릿을 수정해야 할 때 사용
  • 제어 장치 : $ scope 데이터를 공유 / 재사용해야 할 때 사용
  • link : 이벤트 핸들러를 첨부하거나 DOM을 조작 할 때 사용되는 함수입니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.