angularjs - register - directive 뜻




각도 지시문-컴파일, 컨트롤러, 사전 링크 및 사후 링크를 사용할시기와 방법 (6)

Angular 지시문을 작성할 때 다음 함수 중 하나를 사용하여 지시어가 선언 된 요소의 DOM 동작, 내용 및 모양을 조작 할 수 있습니다.

  • 엮다
  • 제어 장치
  • 사전 연결
  • 사후 링크

어떤 기능을 사용해야할지 혼란 스러울 것 같습니다. 이 질문은 다음을 포함합니다.

지시어 기본 사항

  • 다양한 기능을 선언하는 방법?
  • 소스 템플릿인스턴스 템플릿 의 차이점은 무엇입니까?
  • 어떤 순서로 지시문 함수가 실행됩니까?
  • 이 함수 호출 간에는 다른 어떤 일이 발생합니까?

기능 자연,하지 마세요

  • Compile
  • Controller
  • Pre-link
  • Post-link

관련 질문 :


다양한 기능을 선언하는 방법?

컴파일, 컨트롤러, 사전 링크 및 사후 링크

4 가지 기능을 모두 사용하려면 지시문이 다음 형식을 따릅니다.

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return {
                pre: function preLink( scope, element, attributes, controller, transcludeFn ) {
                    // Pre-link code goes here
                },
                post: function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here
                }
            };
        }
    };  
});

compile은 pre-link와 post-link 함수를 모두 포함하는 객체를 리턴한다; Angular lingo에서 우리는 컴파일 함수가 템플릿 함수를 반환한다고 말합니다.

컴파일, 컨트롤러 및 포스트 링크

pre-link 가 필요하지 않은 경우, 컴파일 함수는 다음과 같이 정의 객체 대신 링크 후 함수를 반환 할 수 있습니다.

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here                 
            };
        }
    };  
});

때로는, (post) link 메소드가 정의 된 후에 compile 메소드를 추가하기를 원합니다. 이를 위해 다음을 사용할 수 있습니다.

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.

            return this.link;
        },
        link: function( scope, element, attributes, controller, transcludeFn ) {
            // Post-link code goes here
        }

    };  
});

컨트롤러 및 사후 링크

컴파일 함수가 필요하지 않으면 선언을 모두 건너 뛰고 지시문 구성 객체의 link 속성 아래에 사후 링크 함수를 제공 할 수 있습니다.

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

컨트롤러 없음

위의 예에서 필요하지 않은 경우 controller 기능을 간단하게 제거 할 수 있습니다. 예를 들어 post-link 기능 만 필요한 경우 다음을 사용할 수 있습니다.

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

사전 연결 기능

각 지시어의 pre-link 함수는 새로운 관련 요소가 인스턴스화 될 때마다 호출됩니다.

컴파일 순서 섹션에서 이전에 보았던 것처럼, pre-link 함수는 parent-then-child라고 불리는 반면, post-link 함수는 child-then-parent 라고 불립니다.

pre-link 기능은 거의 사용되지 않지만 특별한 시나리오에서는 유용 할 수 있습니다. 예를 들어 자식 컨트롤러가 부모 컨트롤러에 자신을 등록 할 때 등록이 parent-then-child ( parent-then-child fashion)에 ngModelController parent-then-child ( ngModelController 는 이런 식으로 일을합니다).

하지 마라:

  • 하위 요소를 검사합니다 (아직 렌더링되지 않았거나 범위에 바인딩 된 등).

어떤 순서로 지시문 함수가 실행됩니까?

단일 지시문의 경우

다음과 같은 HTML 마크 업을 고려해보십시오.

<body>
    <div log='some-div'></div>
</body>

다음 지시문 선언을 사용하십시오.

myApp.directive('log', function() {

    return {
        controller: function( $scope, $element, $attrs, $transclude ) {
            console.log( $attrs.log + ' (controller)' );
        },
        compile: function compile( tElement, tAttributes ) {
            console.log( tAttributes.log + ' (compile)'  );
            return {
                pre: function preLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (pre-link)'  );
                },
                post: function postLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (post-link)'  );
                }
            };
         }
     };  

});

콘솔 출력은 다음과 같습니다.

some-div (compile)
some-div (controller)
some-div (pre-link)
some-div (post-link)

우리는 compile 이 먼저 실행 된 다음 controller 가 실행 된 후 pre-link 와 last가 post-link 있습니다.

중첩 된 지시어

참고 : 다음은 링크 기능에서 자녀를 렌더링하는 지시문에는 적용되지 않습니다. 아주 몇몇 Angular 지시어 (ngIf, ngRepeat 또는 transclude가있는 지시문과 같이)가 있습니다. 이러한 지시문은 자식 지시문을 compile 하기 전에 호출되는 link 함수를 기본적으로 호출합니다.

원래 HTML 마크 업은 중첩 된 요소로 만들어지며 각 요소는 고유 한 지시문을 사용합니다. 다음 마크 업 에서처럼 ( plunk 참조) :

<body>
    <div log='parent'>
        <div log='..first-child'></div>
        <div log='..second-child'></div>
    </div>
</body>

콘솔 출력은 다음과 같습니다.

// The compile phase
parent (compile)
..first-child (compile)
..second-child (compile)

// The link phase   
parent (controller)
parent (pre-link)
..first-child (controller)
..first-child (pre-link)
..first-child (post-link)
..second-child (controller)
..second-child (pre-link)
..second-child (post-link)
parent (post-link)

컴파일 단계와 링크 단계의 두 단계를 구분할 수 있습니다.

컴파일 단계

DOM을로드 할 때 Angular는 컴파일 단계를 시작합니다. 여기서 컴파일 단계에서 마크 업을 위에서 아래로 가로 지르고 모든 지시문에서 compile 을 호출합니다. 그래픽 적으로 다음과 같이 표현할 수 있습니다.

이 단계에서 컴파일 함수가 가져 오는 템플릿은 소스 템플릿 (인스턴스 템플릿이 아님)이라고 언급하는 것이 중요합니다.

링크 단계

DOM 인스턴스는 종종 DOM에 렌더링되는 소스 템플릿의 결과이지만 ng-repeat 의해 생성되거나 즉시 도입 될 수 있습니다.

지시어가있는 요소의 새 인스턴스가 DOM에 렌더링 될 때마다 연결 단계가 시작됩니다.

이 단계에서 Angular는 controller 호출하고 pre-link 를 걸며 아이들을 반복하고 모든 지시문에서 post-link 를 호출합니다.


이 함수 호출 간에는 다른 어떤 일이 발생합니까?

다양한 지시문 함수는 $compile (지시문의 compile 이 실행되는 곳)과 nodeLinkFn (지시어의 controller , preLinkpostLink 가 실행되는 곳)이라는 내부 함수라는 두 가지 각도 함수에서 실행됩니다. 지시 함수가 호출되기 전과 후에 각도 함수 내에서 다양한 일이 발생합니다. 아마도 가장 중요한 것은 자식 재귀입니다. 다음의 간단한 그림은 컴파일 및 링크 단계의 주요 단계를 보여줍니다.

이러한 단계를 설명하기 위해 다음 HTML 마크 업을 사용 해보자.

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

다음 지시문을 사용합니다.

myApp.directive( 'myElement', function() {
    return {
        restrict:   'EA',
        transclude: true,
        template:   '<div>{{label}}<div ng-transclude></div></div>'
    }
});

엮다

compile API는 다음과 같이 보입니다.

compile: function compile( tElement, tAttributes ) { ... }

매개 변수에는 종종 인스턴스의 요소가 아닌 소스 템플릿의 요소 및 특성이 있음을 나타 내기 위해 접두사 t 가 붙습니다.

중첩 된 내용 (있는 경우)을 compile 하기 전에 호출이 제거되고 템플리트가 태그에 적용됩니다. 따라서 compile 함수에 제공되는 요소는 다음과 같이 보입니다.

<my-element>
    <div>
        "{{label}}"
        <div ng-transclude></div>
    </div>
</my-element>

이 시점에서 변환 된 콘텐츠는 다시 삽입되지 않습니다.

지시문의 .compile 호출 후 Angular는 지시문에서 방금 소개 한 요소 (예 : 템플릿 요소)를 포함하여 모든 자식 요소를 트래버스합니다.

인스턴스 생성

우리의 경우 위의 소스 템플릿의 세 인스턴스가 생성됩니다 ( ng-repeat 의해). 따라서 다음 시퀀스는 인스턴스 당 한 번 세 번 실행됩니다.

제어 장치

controller API는 다음을 포함합니다.

controller: function( $scope, $element, $attrs, $transclude ) { ... }

링크 단계에 들어가면 $compile 통해 반환 된 링크 함수에 범위가 제공됩니다.

먼저, 링크 함수는 요청 된 경우 하위 범위 ( scope: true ) 또는 격리 된 범위 ( scope: {...} )를 만듭니다.

그런 다음 컨트롤러가 실행되고 인스턴스 요소의 범위가 제공됩니다.

사전 연결

pre-link API는 다음과 같습니다.

function preLink( scope, element, attributes, controller ) { ... }

지시어의 .controller 호출과 .preLink 함수 사이에는 아무 것도 일어나지 않습니다. Angular는 각 방법을 사용하는 방법에 대한 권장 사항을 제공합니다.

.preLink 호출에 이어 링크 함수는 각 하위 요소를 통과합니다. 올바른 링크 함수를 호출하고 현재 범위 (하위 요소의 부모 범위로 .preLink 연결합니다.

포스트 링크

post-link API는 pre-link 기능과 유사합니다.

function postLink( scope, element, attributes, controller ) { ... }

아마도 지시어의 .postLink 함수가 호출되면 모든 children의 .postLink 함수를 포함하여 모든 children 요소의 링크 프로세스가 완료 .postLink 있습니다.

즉, .postLink 가 호출 될 때까지 자식이 '라이브'상태가됩니다. 여기에는 다음이 포함됩니다.

  • 데이터 바인딩
  • 탈락
  • 첨부 된 범위

이 단계의 템플릿은 다음과 같이 표시됩니다.

<my-element>
    <div class="ng-binding">
        "{{label}}"
        <div ng-transclude>                
            <div class="ng-scope">Inner content</div>
        </div>
    </div>
</my-element>

컴파일 기능

각 지시어의 compile 함수는 Angular bootstrap 일 때 한 번만 호출됩니다.

공식적으로 이것은 범위 또는 데이터 바인딩을 포함하지 않는 템플릿 조작 (소스)을 수행하는 곳입니다.

주로 최적화 목적으로 수행됩니다. 다음 마크 업을 고려하십시오.

<tr ng-repeat="raw in raws">
    <my-raw></my-raw>
</tr>

<my-raw> 지시문은 특정 DOM 마크 업 세트를 렌더링합니다. 그래서 우리는 다음 중 하나를 할 수 있습니다 :

  • ng-repeat 를 사용하여 소스 템플릿 ( <my-raw> )을 복제 한 다음 각 인스턴스 템플릿의 마크 업을 수정합니다 ( compile 함수 외부).
  • 원하는 마크 업을 포함하도록 소스 템플릿을 수정 한 다음 ( compile 함수에서) ng-repeat 를 복제하도록 허용하십시오.

raws 컬렉션에 1000 개의 항목이있는 경우 후자의 옵션은 이전 컬렉션보다 빠를 수 있습니다.

해야 할 것:

  • 인스턴스 (클론)에 대한 템플릿 역할을하도록 마크 업을 조작합니다.

하지 마라

  • 이벤트 처리기를 연결하십시오.
  • 하위 요소를 검사하십시오.
  • 속성에 대한 관측치를 설정하십시오.
  • 스코프에서 시계를 설정하십시오.

소스 템플릿인스턴스 템플릿 의 차이점은 무엇입니까?

Angular가 DOM 조작을 허용한다는 사실은 컴파일 프로세스의 입력 마크 업이 출력과 다를 수 있음을 의미합니다. 특히, 일부 입력 마크 업은 DOM에 렌더링되기 전에 ng-repeat 와 같이 몇 번 복제 될 수 있습니다.

각도 용어는 약간 일관성이 없지만 여전히 두 가지 유형의 마크 업을 구별합니다.

  • 소스 템플릿 - 필요할 경우 복제 할 마크 업입니다. 복제 된 경우이 마크 업은 DOM에 렌더링되지 않습니다.
  • 인스턴스 템플릿 - DOM에 렌더링 될 실제 마크 업입니다. 복제가 관련되면 각 인스턴스는 복제본이됩니다.

다음 마크 업에서는이를 보여줍니다.

<div ng-repeat="i in [0,1,2]">
    <my-directive>{{i}}</my-directive>
</div>

근원 HTML는 정의한다

    <my-directive>{{i}}</my-directive>

소스 템플릿으로 사용됩니다.

그러나 ng-repeat 지시문에 포함되어 ng-repeat 원본 템플릿이 복제됩니다 (이 경우에는 3 번). 이러한 복제본은 인스턴스 템플릿이며 각 템플릿은 DOM에 표시되며 관련 범위에 바인딩됩니다.







angularjs-directive