Directive는 HTML에게 새로운 트릭을 연주하도록 가르치는 방법입니다. DOM 컴파일 동안 지시문은 HTML과 실행됩니다. 이를 통해 지침 등록 동작 또는 DOM 구조를 변환 할 수 있습니다.
Angular에는 웹 앱을 구축하는 데 매우 유용한 내장 지침 세트가 제공됩니다. 계속 확장되면 HTML에서 도메인 별 언어 (DSL)를 정의 할 수 있습니다.
1. HTML의 인용문
Directive에는 Ngbind와 같은 낙타 케이스 스타일 명명이 있습니다 (특성에서는 사용할 수없는 것 같습니다 ~). 그러나 지침은 또한 뱀 바닥 유형 (뱀 케이스)으로 이름을 지정할 수 있으며 (콜론), - (마이너스) 또는 _ (밑줄)를 통해 연결해야합니다. 선택적 옵션으로, 지시문은 HTML 검증 요구를 충족시키기 위해 "x-"또는 "data-"로 접두사를 할 수 있습니다. 다음은 법적 지침 이름입니다.
지침은 요소 이름, 속성, 클래스 및 주석으로 배치 할 수 있습니다. 다음은 Mydir, 지침을 인용하는 동등한 방법입니다. (그러나 많은 지침은 "속성"의 사용으로 제한됩니다)
<span my-dir = "exp"> </span> <span> </span> <my-dir> </my-dir> <!-지침 : my-dir exp->
지침은 다양한 방식으로 인용 될 수 있으며 다음은 N 등가를 목록에 있습니다.
<! docType html> <html lang = "Zh-Cn"ng-app> <head> <meta charset = "utf-8"> <title> invoke-directive </title> <style type = "text/css"> .ng-cloak {display : none; . ng_bind = "name"<span ng_bind = "name"> </span> <br/> ng-bind = "name"<span ng-bind = "name"> </span> <br/> data-ng-bind = "name"<span data-ng-bind = "name"> </span> <br/> x-ng-bind = "<span" x-ng-bind = "name"> </span> <br/ <br/ <br/> </div> <script src = "../ Angular-1.0.1.js"type = "text/javaScript> <script type ="text/javaScript "> function myctrl ($ scope) {$ scope.name ="beauty ~~ "; } </script> </body> </html>2. 문자열 보간
컴파일 프로세스 중에 컴파일러는 $ interpolate 서비스를 통해 속성 (예 : {{something}})의 내장 된 표현식과 텍스트와 일치합니다. 이 표현식은 시계로 등록되며 Digest Cycle의 일부로 함께 업데이트됩니다 (이전에는 Digest-Loop가 아니 었습니까?!). 간단한 보간은 다음과 같습니다.
<img src = "img/{{username}}. jpg"/> hello {{username}}!
3. 컴파일 프로세스 및 지침 매칭
HTML을 "컴파일하는 세 단계 :
1. 먼저 브라우저의 표준 API를 통해 HTML을 DOM 객체로 변환하십시오. 이것은 매우 중요한 단계입니다. 템플릿은 구문 분석 할 수 있어야하므로 (사양을 준수). 이것은 대부분 DOM 요소가 아닌 문자열을 기반으로하는 대부분의 템플릿 시스템과 비교할 수 있습니다.
2. DOM의 컴파일은 $ comple () 메소드를 호출하여 수행됩니다. 이 방법은 DOM을 가로 지르고 지침과 일치합니다. 경기가 성공하면 해당 DOM과 함께 지시 목록에 추가됩니다. 지정된 DOM과 관련된 모든 지시문이 식별되는 한 우선 순위로 정렬되고 해당 순서대로 Compile () 함수를 실행합니다. Directive Compile Function은 DOM 구조를 수정할 수있는 기회가 있으며 Link () 함수의 구문 분석을 생성 할 책임이 있습니다. $ compile () 메소드는 결합 된 링크 함수를 리턴합니다.이 함수는 지침 자체의 compile 함수에 의해 리턴 된 연결된 함수 모음입니다.
3. 이전 단계에서 반환 된 연결 함수를 통해 템플릿을 범위에 연결하십시오. 이로 인해 Directive의 자체 링크 기능을 호출하여 요소에 일부 청취자를 등록하고 스코프가있는 시계를 만들 수 있습니다. 결과는 스코프와 DOM 사이의 양방향, 즉각적인 결합입니다. 범위가 변경되면 DOM은 해당 응답을 얻습니다.
var $ compile = ...; // 코드에 주입 됨 var scope = ...; var html = '<div ng-bind ='exp '> </div>'; // 1 단계 : DOM 요소 Var 템플릿에 html을 구문 분석 = Angular.element (html); // 2 단계 : 템플릿을 컴파일하기 var linkfn = $ compile (템플릿); // 3 단계 : 컴파일 된 템플릿을 범위와 연결합니다. linkfn (범위);
4. 컴파일/링크 분리의 이유
이 시점에서 컴파일 프로세스가 왜 컴파일 및 링크의 두 단계로 나뉘 었는지 궁금 할 것입니다. 이것을 이해하려면 실제 예를 살펴 보겠습니다 (리피터)
hello {{user}}, 당신은 다음과 같은 조치를 가지고 있습니다 : <ul> <li ng-repeat = "action in user.actions"> {action.description}} </li> </ul>간단히 말해서, 우리가 컴파일과 링크의 두 단계를 분리하는 이유는 고리기와 같이 모델이 변경된 후에 해당 DOM 구조를 변경해야하기 때문입니다.
위의 예제가 컴파일되면 컴파일러는 모든 노드를 반복하여 지시문을 찾습니다. {{user}}은 보간 지침의 예입니다. ngrepeat는 또 다른 지침입니다. 그러나 ngrepeat에는 어려움이 있습니다. 사용자의 모든 작업에 대해 새로운 LI를 신속하게 만들 수있는 기능이 필요합니다. 이는 Li를 복제하고 특정 조치를 포함시키는 목적을 충족시키기 위해서는 (여기서 사용자의 동작의 값 중 하나를 나타냅니다) Li 요소의 깨끗한 사본을 유지해야하며, 이는 UL 요소에 클로닝되고 삽입되어야합니다. 그러나 Li 요소를 복제하는 것만으로는 충분하지 않습니다. Li는 또한 올바른 범위에서 지시문 ({action.descriptions}})을 구문 분석 할 수 있도록 편집해야합니다. 원래 방법은 일반적으로 Li 요소의 사본을 삽입 한 다음 컴파일합니다. 그러나 컴파일 프로세스는 DOM 노드 트리를 가로 지르고 지시문을 찾아 실행해야하기 때문에 각 LI 요소의 사본을 컴파일하는 것이 느려집니다. 리피터를 통해 100 개의 항목을 처리 해야하는 컴파일이 있으면 성능 문제가 발생합니다.
문제에 대한 해결책은 컴파일 프로세스를 두 단계로 분류하는 것입니다. 컴파일 스테이지는 모든 지시문을 인식하고 우선 순위별로 정렬하여 연결 스테이지 동안 특정 LI와 특정 범위를 바인딩합니다.
NGREPEAT 컴파일 프로세스가 LI 요소로 떨어지는 것을 방지하기 위해 개별 LI를 별도로 컴파일합니다. Li 요소의 컴파일 결과는 Li 요소에 포함 된 모든 지시문을 포함하는 지침 연결 함수이며, 특정 Li 요소의 사본과 연결할 수 있습니다. 런타임에 NGREPEAT는 표현식을 모니터링하고 LI 요소 사본의 배열에 항목으로 추가되어 클로닝 된 LI 요소에 대한 새로운 범위를 생성하고 사본에 해당하는 링크 기능을 호출합니다.
요약 :
1. 컴파일 함수 - 컴파일 함수는 DOM 요소 (DOM 자체 및 내부 구조)의 템플릿을 변경하는 대신 지정된 DOM 요소와의 작업에만 관심이 있기 때문에 지시문에서는 비교적 드물다. 성능을 최적화하기 위해 지침 인스턴스에서 공유 할 수있는 일부 작업을 컴파일 함수로 이동할 수 있습니다.
2. 링크 기능 - 링크 기능이 거의없는 지시문은 거의 없습니다. 링크 함수를 사용하면 DIMP 기능을 사용하면 DOM 요소 인스턴스의 지정된 사본에 리스너를 등록하거나 범위에서 특정 컨텐츠를 DOM으로 복사 할 수 있습니다.
5. 지침 작성 (간단한 버전)
이 예에서는 입력 형식에 따라 현재 시간을 표시하는 지침을 작성합니다.
<! docType html> <html lang = "zh-cn"ng-app = "timeformat"> <head> <meta charset = "utf-8"> <title-format </title> </head> <div ng-controller = "myctrl"id = "main"> date format : <input ng-model = "format" type = "text"/> <hr/> <!-다음은 x-current time 속성을 사용하여 위에서 언급 한 법적 명명을 시도합니다. -> 현재 시간은 다음과 같습니다. type = "text/javaScript"> angular.module ( "timeformat", []) // 위에서 언급했듯이 "currenttime"의 지시 공장 메소드 등록 // 위에서 언급 한 바와 같이, 의존성 주입은 기능 매개 변수에 직접 작성 될 수 있으며, 여기에 $ timeout 및 datafilter ( "currentfilter (datefilter)는 inturning (datefilter)에 intublter (datefilter) {// inturning (datefilter). 컴파일 함수, 왜? SCOPE. $ watch (attr.currentTime, value) {scope.format = value; updateTime ()); }). 컨트롤러 ( "myctrl", function ($ scope, $ rootscope) {$ scope.format = "m/d/yy h : mm : ss a"; $ scope.remove = function () {var oformat = document.getElementById ( "myformat"); if (ofmat) {angular.element (). $ destrict는 트리거 될 수 있습니다!6. 지침 작성 (자세한 버전)
아래는 지침 (지시 객체 정의 템플릿)의 샘플 작성입니다. 자세한 목록을 보려면 계속 읽으십시오.
var myModule = Angular.Module (...); myModule.Directive ( 'DirectivenAMe', 기능 공장 (주입자) {var DirectivedEfinitionObject = {우선 순위 : 0, 템플릿 : '<div> </div>', templateUrl : 'divistive.html', 교체 : false, transclude : false, 'a', 'scope : false, compile : function, transtrs, transtrs. PRELINK (SCOPE, IELEMENT, IATTRS, 컨트롤러) {...}, PostLink (SCOPE, IELEMENT, IATTRS, CONTROLER) {...}}} : 함수 PostLink (SCOPE, IELENT, IATTRS) {...}};대부분의 시나리오에서는 정확한 제어가 필요하지 않으므로 위의 정의를 단순화 할 수 있습니다. 템플릿의 각 부분을 정의하면 다음 장에서 설명됩니다. 이 장에서는 템플릿을 정의하는이 골격의 이성질체에만 중점을 둡니다 (이 골격의 이성질체, 이해가 안 돼요 ... 모든 사람의 추가를 기대합니다).
코드를 단순화하는 첫 번째 단계는 기본값에 의존하는 것입니다. 따라서 위의 코드를 단순화 할 수 있습니다.
var myModule = Angular.Module (...); myModule.directive ( 'Directivename', Function Factory (Injectables) {var DirectivedEfinitionObject = {Compile : 함수 컴파일 (Telement, Tattrs) {return function postLink (SCOPE, IELENT, IATTRS) {...}}}; Return DirectIvedEfinitionObject;});대부분의 지시문은 템플릿 변환이 아닌 인스턴스에만 관심이 있으므로 더 단순화 할 수 있습니다 (매우 열심히 번역 ... 모든 사람의 추가를 기대합니다) :
var myModule = Angular.Module (...); myModule.Directive ( 'DirectivenAMe', Function Factory (Injectables) {return function postLink (SCOPE, IELEMENT, IATTRS) {...}});7. 공장 방법
공장 방법은 지시문을 작성할 책임이 있습니다. 컴파일러가 지시문과 처음 일치 할 때만 한 번만 사용됩니다. 여기에서 몇 가지 초기화 작업을 수행 할 수 있습니다. 공장 방법은 $ injector.invoke를 통해 실행되므로 모든 주입 선언 규칙 (주입 주석 규칙)을 준수하여 주입 할 수 있습니다.
8. 지침 정의 객체 설명
지침 정의 객체는 컴파일러 구조를 제공합니다. 속성은 다음과 같습니다.
1. 이름 - 현재 범위의 이름. 등록 할 때 기본값을 사용할 수 있습니다 (채워지지 않음).
2. 운반- 동일한 DOM 요소에 여러 개의 지시문이 정의 된 경우 때로는 실행 순서를 명확히해야합니다. 이 속성은 지침 컴파일 함수 호출 전에 정렬하는 데 사용됩니다. 우선 순위가 동일하다면, 실행 순서가 불확실하다면 (예비 실험 후에, 우선 순위가 높은 사람들은 먼저 실행되며, 동일한 레벨은 "사후 바인딩"실행 우선 "과 유사합니다. 또한 테스트 중에는 약간 부주의했습니다. 지침을 정의 할 때 두 번 정의되었지만, 두 가지 성적 또는 연결 결과가 발견되었음을 발견했습니다).
3. 터미널 (마지막 그룹) - "true"로 설정되면 현재 우선 순위가 마지막 실행 그룹의 지침이 될 것임을 의미합니다. 지침이 현재 우선 순위와 동일하다면 여전히 실행되지만 주문은 불확실합니다 (순서는 불확실하지만 기본적으로 우선 순위와 동일합니다. 현재 우선 순위가 실행 된 후에는 우선 순위가 낮아지지 않습니다).
4.Scope- 설정된 경우 :
1) .true-이 지침을위한 새로운 범위가 만들어집니다. 동일한 요소에 새로운 범위가 필요한 여러 지시문이있는 경우에도 여전히 하나의 범위 만 생성됩니다. 새로운 스코프 규칙은 루트 템플릿에는 적용되지 않으므로 루트 템플릿은 새로운 범위를 얻는 경향이 있습니다.
2). {} (Object Hash) - 새로운 분리 범위가 생성됩니다. "분리"범위와 일반 범위의 차이점은 프로토 타입을 통해 상위 범위에서 상속되지 않는다는 것입니다. 이는 재사용 가능한 구성 요소를 작성하는 데 매우 도움이되며 부모 범위에서 데이터를 읽거나 수정하는 것을 효과적으로 방지 할 수 있습니다. 이 독립적 인 범위는 상위 스코프에서 파생 된 로컬 스코프 속성 세트가있는 객체 해시를 만듭니다. 이 로컬 속성은 템플릿 -_-!의 값을 별칭하는 데 유용합니다. 현지인 정의는 소스#&) $ &@#)에 대한 로컬 스코프 속성의 해시입니다 ($ &@#_) :
3). @ 또는 @attr- DOM 속성에 로컬 범위 속성을 만듭니다. 속성 값은 항상 문자열 유형 이므로이 값은 항상 문자열을 반환합니다. 속성 이름이 @attr을 통해 지정되지 않은 경우 로컬 이름은 항상 dom 속성의 이름을 갖습니다. 예를 들어, <widget my-attr =”hello {{name}} ">, 위젯의 범위는 다음과 같이 정의됩니다. {localname : '@myattr'}. 그런 다음 위젯 범위 속성의 로컬 이름은 "hello {{name}}"으로 변환 된 실제 값을 매핑합니다. 이름 속성 값이 변경되면 위젯 범위의 LocalName 속성도 그에 따라 변경됩니다 (아래의 "="와는 다른 일방 통행). 이름 속성은 상위 스코프에서 읽습니다 (구성 요소 범위가 아님)
4). = 또는 = expression (여기서 attr attr) - 로컬 스코프 속성과 상위 스코프 속성 사이의 양방향 바인딩을 설정합니다. attr 이름이 지정되지 않은 경우 로컬 이름은 속성 이름과 일치합니다. 예를 들어, <widget my-attr =”parentmodel”>, 위젯으로 정의 된 범위는 다음과 같습니다. ParentModel에서 변경 사항이 발생하면 LocalModel도 변경되며 그 반대도 마찬가지입니다. (이중 웨이 바인딩)
5). & or & attr- 부모 범위 컨텍스트에서 표현식을 실행하는 방법을 제공합니다. attr 이름이 지정되지 않은 경우 로컬 이름은 속성 이름과 일치합니다. 예를 들어, <Widget my-attr =”count = count + value”>, 위젯의 범위는 다음과 같이 정의됩니다. {localfn : 'excrement ()'}이면 스코프 속성을 분리하여 "localfn"은 증분 () 표현식으로 랩핑 된 함수를 가리 킵니다. 일반적으로, 우리는 표현식을 통해 분리 범위에서 부모 범위로 데이터를 전달하려고합니다. 이것은 로컬 변수의 키 값의 맵을 표현식의 래퍼 함수로 전달하여 수행 할 수 있습니다. 예를 들어, 표현식이 증분 (금액) 인 경우 localfn ({and {and {금 : 22})을 통해 localfn을 호출하여 금액의 값을 지정할 수 있습니다 (위의 예는 실제로 이해하지 못하고 어디로 갔습니까?).
5. 콘트롤러 - 컨트롤러 생성자. 컨트롤러는 사전 링크 단계 전에 초기화하고 필요한 이름을 통해 다른 지시문을 공유 할 수 있도록합니다 (아래 요구 사항 참조). 이를 통해 지시문은 서로 의사 소통하고 상호 행동을 향상시킬 수 있습니다. 컨트롤러는 기본적으로 다음 로컬 객체를 주입합니다.
1). $ 범위 - 범위는 현재 요소와 결합됩니다
2). $ 요소 - 현재 요소
3). $ attrs- 현재 요소의 속성 객체
4). $ transclude- 전류 링크 함수 전류 전환 범위에 사전 바인딩 : 함수 (clonelinkingfn). (올바른 변환 범위에 사전 바운드 함수를 링크하는 트랜스 클럽 링크)
6. 요청 - 다른 컨트롤러가 현재 지침 링크 함수로 전달하도록 요청하십시오. 직접 컨트롤러의 이름이 전달되어야합니다.이 이름에 해당하는 컨트롤러를 찾을 수 없으면 오류가 발생합니다. 이름은 다음과 같이 접두사를 할 수 있습니다.
1).? - 예외를 던지지 마십시오. 이것은 이러한 종속성을 옵션으로 만듭니다.
2).^ - 부모 요소를 검색 할 수있는 컨트롤러
7. RESTRICT- 지정된 선언 방법으로 지시를 제한하는 EACM의 하위 집합 문자열. 생략하면 지시문은 속성을 통해서만 선언을 허용합니다.
1) E- 요소 이름 : <내 디렉티브> </my-directive>
2) .a- 속성 이름 : <div my -directive =”exp”> </div>
3). C- 클래스 이름 : <div class = "my -directive : exp;"> </div>
4) .m- 의견 : <!-지침 : 내 지시적 Exp->
8. TEMPLATE- 대체가 참이면 템플릿 내용을 현재 HTML 요소로 바꾸고 원래 요소의 속성 및 클래스를 마이그레이션하십시오. false 인 경우 템플릿 요소는 현재 요소의 자식 요소로 취급됩니다. 자세한 내용은 "위젯 만들기"장을 확인하십시오 (여기서 ... 구성 요소 생성 가능 ...)
9.templateUrl- 기본적으로 템플릿과 동일하지만 템플릿은 지정된 URL을 통해로드됩니다. 템플릿 로딩이 비동기식이기 때문에 편집 및 연결이 일시 중지되고 로딩 후에 실행됩니다.
10. REPLAPE- true로 설정되면 템플릿은 현재 요소에 자식 요소로 추가되는 대신 현재 요소를 대체합니다. (참고 : TRUE 일 때 템플릿에는 루트 노드가 있어야합니다)
11. TransClude- 요소의 내용을 지시문으로 사용할 수 있도록 요소의 내용을 컴파일하십시오. (템플릿에서) 사용해야합니다 (참조). 전환의 장점은 연결 함수가 현재 범위에 미리 바인딩되는 번역 함수를 얻을 수 있다는 것입니다. 일반적으로 위젯을 생성하고 분리 범위를 만듭니다. 번역은 아이가 아니라 격리 범위의 형제입니다. 이렇게하면 위젯에 개인 상태가 있으며 트랜스 클레싱은 부모 (사전 이소 레이트) 범위에 묶여 있습니다. (위의 단락을 이해하지 못합니다. 그러나 실제 실험에서 myDirective가 <Any-Directive> {{name}} </any-directive>를 통해 호출되고 transclude가 true 또는 문자열로 설정되어 있고 <etag ng-transclude>를 포함합니다. 랩핑 된 것이 있으면 트랜스 클럽이 '요소'로 설정되면 전체 내용이 SOMENG에 표시되고 P에 의해 포장됩니다.
1) .true-이 지침의 내용을 변환합니다. (이런 의미에서, 그것은 내용을 직접 컴파일하고 지정된 장소로 옮기는 것입니다)
2). '요소' - 우선 순위가 낮은 다른 지시문을 포함하여 전체 요소를 변환합니다. (예를 들어, 전체 컨텐츠를 컴파일 한 후에는 전체로 처리되고 (외부로 포장) 지정된 장소에 삽입됩니다)
12.compile- 다음 장에서 자세히 설명 할 컴파일 함수가 있습니다.
13.link- 다음 장에서는 링크 함수가 있습니다. 다음 장에서 자세히 설명합니다. 이 속성은 컴파일 속성이 정의되지 않은 경우에만 사용됩니다.
9. 함수를 컴파일합니다
기능 컴파일 (Telement, Tattrs, TransClude) {…}
컴파일 기능은 DOM 템플릿의 변환을 처리하는 데 사용됩니다. 대부분의 지시문에는 변환 템플릿이 필요하지 않으므로 컴파일은 자주 사용되지 않습니다. 컴파일 함수, 일반적으로 DOM 템플릿 (예 : NGREPEAT)을 변환 해야하는 기능 또는 컨텐츠 비동기 적으로 (예 : NGVIEW)를로드 해야하는 지침. 컴파일 함수에는 다음 매개 변수가 있습니다.
1. 텔레멘트 - 템플릿 요소는 현재 지침 요소를 사용합니다. 현재 요소 또는 현재 요소 하위 요소에서 템플릿 변환을 수행하는 것이 안전합니다.
2. TATTRS- 템플릿 속성 - 현재 요소에 선언 된 표준화 된 속성은 다양한 지시문간에 공유 할 수 있습니다. 자세한 내용은 속성 장을 참조하십시오
3. 변환에 대한 연결 함수를 전송합니다 : 함수 (범위, 클론 링킹).
참고 : 템플릿이 복제 된 경우 템플릿 인스턴스와 링크 인스턴스가 동일한 객체가 될 수 없습니다. 이렇게하려면 컴파일 함수에서 DOM 변환 이외의 다른 일을하는 것이 안전하지 않으며, 이는 모든 클론에 적용됩니다. 특히, DOM 이벤트 리스너의 등록 작업은 컴파일 함수가 아닌 연결 함수에서 수행되어야합니다.
컴파일 함수는 리턴 값을 가질 수 있으며 유형은 함수 또는 객체 일 수 있습니다.
1. 반환 함수는 일반적으로 컴파일 함수가 필요하지 않은 경우 (빈)가 필요하며 링크를 통해 연결 함수를 등록하는 것과 같습니다 (템플릿의 속성을 직접 정의 함).
2. 사전 및 사후 특성을 포함하는 객체를 반환합니다 - 연결 위상에서 연결 함수가 호출 될 때 제어 할 수 있습니다. 자세한 내용은 사전 연결 및 사후 연결 기능에 대한 다음 장을 참조하십시오.
10. 연결 함수
함수 링크 (범위, IELEMENT, IATTRS, 컨트롤러) {…}
링크 함수는 DOM 이벤트 리스너 등록을 담당하며 DOM 업데이트 작업을 수행 할 수도 있습니다. 템플릿 클로닝 작업이 완료된 후 링크 함수가 실행됩니다. 지침 논리의 대부분은 여기에 저장됩니다.
1.Scope -Scope-는 시계를 등록하는 데 사용됩니다 (http://docs.angularjs.org/api/ng.$rootscope.scope#$watch).
2.ILENTER- 요소 인스턴스 - 지침에 사용되는 요소. 포스트 링크 함수의 자식 요소에서 작동하는 것이 안전합니다. 하위 요소가 연결되어 있기 때문에 (모델에 연결되어 있습니까?!).
3. IITTRS- 속성 인스턴스 - 표준 전류 요소의 속성 목록. 모든 지침 연결 기능간에 공유됩니다.
4. Controller- 컨트롤러 인스턴스 - 컨트롤러 중 하나가 현재 요소의 지시에 정의되면 여기에서 컨트롤러 인스턴스를 얻을 수 있습니다. 이 컨트롤러는 모든 지시문들 사이에서 공유되며, 각 지침은 컨트롤러를 그들 사이의 통신 채널로 취급 할 수 있습니다.
사전 링크 기능
자식 요소가 연결되기 전에 실행하십시오. 컴파일러의 연결 함수가 링크 할 때 올바른 요소를 찾지 못할 수 있기 때문에 DOM 변환을 수행하는 것은 안전하지 않습니다.
링크 후 기능
자식 요소가 연결된 후 실행하십시오. 여기서 DOM 변환을 수행하는 것이 안전합니다.
11. 속성
속성 객체 - inlink () 또는 compile ()의 arguments는 다음에 액세스하는 방법입니다.
1. 표준화 된 속성 이름 : ngbind와 같은 지침 때문에 "ng : bind", "x-ng-bind"와 같은 여러 형태로 나타날 수 있습니다.
2. 지침 간 통신 : 모든 지시문은 속성 객체 인스턴스를 공유하여 지시문이 속성 객체를 통해 지시문간에 통신 할 수 있도록합니다.
3. 지원 보간 : 보간 속성은 속성 객체에 할당되어 다른 지시문이 보간 된 값을 읽을 수 있습니다.
4. 보간 된 속성을 관찰하십시오. 보간을 포함하여 attr. $ artebe (예 : src =”{{bar}} ")를 통해 attr. $ 관찰을 통해 속성 값의 변경 사항을 관찰하십시오. 그것은 매우 효과적 일뿐 만 아니라 단순히 실제 가치를 얻는 유일한 방법이기도합니다. 연결 단계에서 보간이 할당되지 않았으므로 (실제 값으로 대체 됨) 현재 액세스 할 때 결과가 정의되지 않습니다.
<! doctype html> <html lang = "Zh-Cn"ng-app = "DirectiveProperty"> <head> <meta charset = "utf-8"> <title> Directive-Attribute-Test> <Style Type = "text/css"> .ng-cloak {display : 없음; }. type = "text/javaScript"> </script> <script type = "text/javaScript"> var app = Angular.Module ( "DirectiveProperty", []); app.controller ( "myctrl", function ($ scope) {$ scope.name = "my little dada";}); var directivep2 = app.directive ( "directivep2", function () {return {link : function postLink (scope, lele, lattr) {console.log ( "myAttr :" + lattr.myattr); // 123 console.log ( "myattr :" + lattr.attrdd); Console.log (attdd는 값을 ' + 값으로 변경했습니다12. 전환 및 범위를 이해하십시오
우리는 종종 재사용 가능한 구성 요소가 필요합니다. 다음은 간단한 대화 상자 구성 요소가 작동하는 방법을 보여주는 의사 코드입니다.
<button ng-click = "show = true"> show </button> <대화 표시 = "show"on-cancel = "show = false"on-ok = "show = false; dosomething ()"> Body가 여기 간다 : {{username}} is {{title}}. </dialog>"표시"버튼을 클릭하면 대화 상자가 열립니다. 대화 상자에는 데이터 "사용자 이름"에 바인딩되는 제목이 있으며 대화 상자 내부에 배치하려는 단락도 있습니다.
다음은 대화 상자에 대해 작성된 템플릿 정의입니다.
<div ng-show = "show ()"> <h3> {{title}} </h3> <div ng-transclude> </div> <div> <button ng-click = "onok ()"> 저장 변경 </button> <button ng-click = "oncancel ()" "> close </button> </div> </div>우리가 범위에 대해 특별한 치료를하지 않는 한 이것은 올바르게 렌더링되지 않습니다.
우리가 해결해야 할 첫 번째 문제는 대화 상자 템플릿이 제목을 정의 할 것으로 예상하고 초기화 될 때 사용자 이름에 바인딩된다는 것입니다. 또한 버튼은 ONOK와 ONCANCEL의 두 기능이 범위에 나타나야합니다. 이것은 위젯의 유용성을 제한합니다.). 매핑 문제를 해결하기 위해, 템플릿에서 예상되는 로컬 변수는 다음 지역 메소드에 의해 생성됩니다 (현지인은 지침 정의 템플릿의 범위로 추정 됨)
범위 : {title : 'bind', // 데이터 바인딩 수락 onok : 'expression', // 대의원 함수 oncancel : 'expression', // 델리게이트 ONCANCEL 함수 만들기 : 'Accessor'// 가시성을 위해 getter/setter 함수를 만듭니다.}}.제어 범위에서 로컬 속성 생성은 두 가지 문제가됩니다.
1. 격리 (속성 격리?) - 사용자가 컨트롤 템플릿에서 요소 속성 제목을 설정하는 것을 잊어 버리면 제목이 조상 범위 (있는 경우)의 속성 "제목"에 바인딩됩니다. 이것은 예측할 수없고 바람직하지 않습니다.
2. 전환 - 번역 된 DOM은 제어의 현지인 (분리 범위?)을 볼 수 있습니다. 현지인들은 실제로 전환에 묶여 있어야하는 속성을 무시합니다. 이 예에서는 플러그인의 제목 속성이 트랜스 클레싱의 제목 속성을 파괴합니다.
속성 격리의 부족 문제를 해결하려면이 지침에 대한 격리 된 범위를 정의해야합니다. 분리 된 범위는 아동 스코프의 프로토 타입에서 상속되지 않습니다 (아동 스코프 인 이유는 무엇입니까? 부모의 범위가 아닌가?).
그러나 격리 된 범위는 새로운 문제를 일으킨다. 번역 된 DOM이 위젯 분리 된 범위의 자식이라면 아무것도 바인딩 할 수 없습니다. 따라서 번역 된 범위는 컨트롤이 로컬 속성의 격리 된 범위를 생성하기 전에 생성 된 원래 범위의 자식 범위입니다. 번역 된 스코프와 격리 된 범위는 형제 노드 (스코프 트리)에 속합니다.
이것은 예기치 않게 복잡해 보일 수 있지만, 그렇게하면 최소한 사용자를 제어하고 개발자를 제어하는 데 놀라움이 생깁니다. (문제가 해결되었습니다)
따라서 최종 지침 정의는 대략 다음과 같습니다.
transclude : true, scope : {title : 'bind', // 데이터 바인딩 수락 onok : // 'expression', // 대의원 함수 oncancel : 'expression', // 델리게이트 Oncancel 함수 만들기 : 'Accessor'// 가시성을 위해 getter/setter 함수 만들기. // 이것을 시도했지만 실패했습니다 ... 계속 읽으십시오}위의 코드를 완전한 예제로 구성하려고 노력했습니다. 직접 복사하면 예상 결과가 달성되지 않습니다. 그러나 약간의 수정 후 플러그인을 실행할 수 있습니다.
<! docType html> <html ng-app = "대화 상자"> <head> <meta http-equiv = "content-type"content = "text/html; charset = utf-8"/> <title> directive-dialog </title> <ee = edge, chrome = 1 "http-equiv ="x-u-compation " src = "../ angular.js"type = "text/javaScript"> </script> </head> <body> <div ng-controller = "myctrl"> <button ng-click = "show = true"> show </button> <대화식 = "{{show}}"show = false; " on-ok = "show = false; methodinparentscope ();"> <!-위의 ancancel 및 on-ok는 지침 분리기 범위에 의해 참조됩니다. 표현식에 함수가 포함 된 경우, 상위 스코프 (현재 MyCtrl Scope)에서 함수를 바인딩해야합니다 (현재 MyCtrl Scope) -> Body : username : {{username}}, 제목 : {{title}}. <ul> <!-여기에서도 이렇게 재생할 수 있습니다 ~ 이름은 부모의 스코프입니다-> <li ng-repeat = "name in names"> {{name}} </li> </ul> </divog> </div> <script type = "text/javaScript"> var myModule = angular.module ( "dialog", []); myModule.controller ( "myctrl", function ($ scope) {$ scope.names = [ "name1", "name2", "name3"]; $ scope.show = false; $ scope.username = "lclao"; $ scope.title = "부모 제목"; $ scope.methodinparentscope () {alert ( "remert) 부모의 범위에서 플레이 !!! ");};}); myModule.directive ( 'dialog', function factory () {return {priority : 100, 템플릿 : [ '<div ng-show = "visible">', '<h3> {{title}} </h3>', '<div ng-transclude> </div>', '<div>', '<</div>', '<bulting ng click = "<div ng-transclude> </div>', '<버튼 ng click = ng-click="onCancel()">Close</button>', ' </div>', ' </div>', ' </div>'].join(""), replace:false, transclude: true, restrict:'E', scope:{ title:"@",//quote the value of the title attribute of the dialog tag onOk:"&",//reference the content of the on-ok attribute of the dialog tag in the 래퍼 함수의 형태 : "&", // 래퍼 함수 형식을 참조하십시오. </script> </body> </html>13. 구성 요소 생성
우리는 일반적으로 복잡한 DOM 구조를 통해 지시문을 대체 할 것으로 예상합니다 (요소는 위치합니까? 목적은 아마도 지침 내부 복잡한 포인트를 만드는 것입니다. 이는 재사용 가능한 구성 요소를 사용하여 응용 프로그램을 구축하는 데 대한 지름길이됩니다.
재사용 가능한 구성 요소의 예는 다음과 같습니다.
<! docType html> <html ng-app = "zippymodule"> <head> <meta http-equiv = "content-type"content = "text/html; charset = utf-8"/> <title> zippymodule </title> <meta content = "ie = edge, chrome = 1"http-u-compative ""zippymodule </title> <메타 내용. <스타일 유형 = "text/css"> .zippy {border : 1px solid black; 디스플레이 : 인라인 블록; 너비 : 250px; } .zippy.opened> .title : everence {content : ''; } .zippy.opened> .Body {display : 블록; } .zippy.closed> .title : everence {content : '►'; } .zippy.closed > .body { display: none; } .zippy > .title { background-color: black; 색상 : 흰색; padding: .1em .3em; cursor: pointer; } .zippy > .body { padding: .1em .3em; } </style> <script src="../angular.js" type="text/javascript"></script></head><body> <div ng-controller="MyCtrl"> Title: <input ng-model="title" type="text"><br/> Text: <textarea ng-model="text"></textarea> <hr/> <div zippy-title="Details: {{title}}...">{{text}}</div> </div> <script type="text/javascript"> var myModule = angular.module("ZippyModule", []); myModule.controller("MyCtrl", function ($scope) { $scope.title = "Here is the title"; $scope.text = "Here is the content... "; }); myModule.directive('zippy', function () { return { template: '<div>' + ' <div>{{title}}</div>' +//This title belongs to the property of the current direct isolate scope ' <div ng-transclude></div>' + //What is here, what is obtained is the property of the parent scope '</div>', replace:true, transclude: true, restrict:'C', scope:{ title:"@zippyTitle"//Bind the zippy-title attribute on the directive element}, link:function(scope,element,attrs) { var title = angular.element(element.children()[0]), opened = false; title.bind("click", toogle); element.addClass("closed"); function toogle() { opened = !opened; element.removeClass(opened ? "closed" : "opened"); element.addClass(opened ? "opened" : "closed"); } } }; }); </script></body></html>