[angularjs] 링크 vs 컴파일 vs 컨트롤러

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

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

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

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

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

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



답변

컴파일 :

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

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

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

연결 단계 :

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

컨트롤러 :

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


답변

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

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

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

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


답변

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
    }
  }
});


답변

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

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

vs.

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


답변

이것은 지시문 단계를 이해하기에 좋은 샘플입니다.
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>


답변

  • 엮다 : 새 표현식 추가,이 지시문 안에 다른 지시문 추가와 같은 지시문 템플릿을 수정해야 할 때 사용
  • 제어 장치 : $ scope 데이터를 공유 / 재사용해야 할 때 사용
  • link : 이벤트 핸들러를 첨부하거나 DOM을 조작 할 때 사용되는 함수입니다.

답변