Angular 지시문을 작성할 때 다음 함수 중 하나를 사용하여 지시문이 선언 된 요소의 DOM 동작, 내용 및 모양을 조작 할 수 있습니다.
- 엮다
- 제어 장치
- 사전 연결
- 사후 링크
어떤 기능을 사용해야하는지 혼동이있는 것 같습니다. 이 질문은 다음과 같습니다.
지시문의 기초
기능 성격,해야 할 것과하지 말아야 할 것
관련 질문 :
답변
지시문 함수는 어떤 순서로 실행됩니까?
단일 지시문
다음 plunk를 기반으로 다음 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
과 마지막이다 post-link
.
중첩 지시문
참고 : 다음은 링크 기능에서 하위를 렌더링하는 지시문에는 적용되지 않습니다. 꽤 많은 Angular 지시어가 그렇게합니다 (ngIf, ngRepeat 또는을 사용하는 지시어
transclude
). 이러한 지시문은 기본적으로 자식 지시문 이 호출 되기 전에link
함수 가 호출됩니다.compile
원래 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
, preLink
그리고 postLink
실행된다). 지시문 함수가 호출되기 전과 후에 각도 함수 내에서 다양한 일이 발생합니다. 아마도 가장 주목할만한 것은 자식 재귀입니다. 다음 단순화 된 그림은 컴파일 및 링크 단계 내의 주요 단계를 보여줍니다.
이러한 단계를 보여주기 위해 다음 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는 지시문에 의해 도입되었을 수있는 요소 (예 : 템플릿 요소)를 포함하여 모든 하위 요소를 순회합니다.
인스턴스 생성
이 경우 위의 소스 템플릿 인스턴스가 3 개씩 생성됩니다 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
호출 후 링크 함수는 각 하위 요소를 순회합니다. 올바른 링크 함수를 호출하고 현재 범위 (하위 요소의 상위 범위 역할을 함)에 연결합니다.
포스트 링크
post-link
API는 pre-link
함수 의 API와 유사 합니다.
function postLink( scope, element, attributes, controller ) { ... }
지시어 .postLink
함수가 호출되면 모든 자식 .postLink
함수를 포함하여 모든 자식 요소의 링크 프로세스가 완료 되었음을 알 수 있습니다.
이것은 시간 .postLink
이 지남 에 따라 아이들이 ‘살아있다’는 것을 의미합니다 . 여기에는 다음이 포함됩니다.
- 데이터 바인딩
- transclusion이 적용됨
- 연결된 범위
따라서이 단계의 템플릿은 다음과 같습니다.
<my-element>
<div class="ng-binding">
"{{label}}"
<div ng-transclude>
<div class="ng-scope">Inner content</div>
</div>
</div>
</my-element>
답변
다양한 함수를 선언하는 방법?
컴파일, 컨트롤러, 프리 링크 및 포스트 링크
하나가 네 가지 기능을 모두 사용하는 경우 지시문은 다음 형식을 따릅니다.
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
};
}
};
});
때로는 compile
(post) 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 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
},
};
});
답변
소스 템플릿 과 인스턴스 템플릿 의 차이점은 무엇입니까 ?
Angular가 DOM 조작을 허용한다는 사실은 컴파일 프로세스에 대한 입력 마크 업이 때때로 출력과 다름을 의미합니다. 특히, 일부 입력 마크 업은 ng-repeat
DOM에 렌더링되기 전에 (와 같은 ) 몇 번 복제 될 수 있습니다 .
각도 용어는 약간 일치하지 않지만 여전히 두 가지 유형의 마크 업을 구분합니다.
- 소스 템플릿 -필요한 경우 복제 할 마크 업입니다. 복제 된 경우이 마크 업은 DOM에 렌더링되지 않습니다.
- 인스턴스 템플릿 -DOM에 렌더링 할 실제 마크 업입니다. 복제가 포함 된 경우 각 인스턴스는 복제본이됩니다.
다음 마크 업이이를 보여줍니다.
<div ng-repeat="i in [0,1,2]">
<my-directive>{{i}}</my-directive>
</div>
소스 HTML은
<my-directive>{{i}}</my-directive>
소스 템플릿으로 사용됩니다.
그러나 ng-repeat
지시문에 래핑 되면이 소스 템플릿이 복제됩니다 (이 경우 3 번). 이 복제본은 인스턴스 템플릿이며 각각 복제본에 표시되며 관련 범위에 바인딩됩니다.
답변
컴파일 기능
compile
Angular 부트 스트랩시 각 지시문의 함수는 한 번만 호출됩니다.
공식적으로 이것은 범위 또는 데이터 바인딩과 관련이없는 템플릿 조작을 수행 할 수있는 곳입니다.
주로 최적화 목적으로 수행됩니다. 다음 마크 업을 고려하십시오.
<tr ng-repeat="raw in raws">
<my-raw></my-raw>
</tr>
<my-raw>
지시어는 DOM 마크 업의 특정 집합을 렌더링합니다. 따라서 다음 중 하나를 수행 할 수 있습니다.
- 허용
ng-repeat
소스 템플릿 (중복<my-raw>
), 다음 (외부 각 인스턴스 템플릿의 마크 업 수정compile
기능). compile
함수 에서 원하는 마크 업을 포함하도록 소스 템플릿을 수정 한 다음ng-repeat
복제하십시오.
raws
컬렉션에 1000 개의 항목이 있으면 후자의 옵션이 이전 옵션보다 빠를 수 있습니다.
하다:
- 마크 업을 조작하여 인스턴스 (클론)에 대한 템플릿 역할을합니다.
하지 마라
- 이벤트 핸들러를 첨부하십시오.
- 자식 요소를 검사하십시오.
- 속성에 대한 관찰을 설정하십시오.
- 스코프에서 시계를 설정하십시오.
답변
컨트롤러 기능
각 지시문의 controller
함수는 새로운 관련 요소가 인스턴스화 될 때마다 호출됩니다.
공식적으로 controller
기능은 다음과 같습니다.
- 컨트롤러간에 공유 될 수있는 컨트롤러 로직 (방법)을 정의합니다.
- 범위 변수를 시작합니다.
또한 지시문에 격리 된 범위가 포함 된 경우 부모 범위에서 상속 된 모든 속성을 아직 사용할 수 없다는 점을 기억해야합니다.
하다:
- 컨트롤러 로직 정의
- 범위 변수 시작
하지 마라:
- 자식 요소를 검사합니다 (아직 렌더링되지 않거나 범위에 바인딩 된 경우 등).
답변
사후 링크 기능
때 post-link
바인딩, 트랜스 클루 전 등 – 함수가 호출 될 때, 이전의 모든 단계가 자리를 차지하게
일반적으로 렌더링 된 DOM을 추가로 조작 할 수있는 곳입니다.
하다:
- DOM (렌더링 및 인스턴스화) 요소를 조작합니다.
- 이벤트 핸들러를 첨부하십시오.
- 자식 요소를 검사하십시오.
- 속성에 대한 관찰을 설정하십시오.
- 스코프에서 시계를 설정하십시오.