높은 수준에서 지시문은 Angularjs의 HTML 컴파일러($compile)에 특정 동작을 이 DOM 요소에 연결하도록 지시하는 데 사용되는 DOM 요소(속성, 요소 이름, 주석 및 CSS 클래스)에 대한 마크업입니다(예: 이벤트를 통해). 청취) 또는 DOM 요소와 해당 하위 요소를 변환할 수도 있습니다.
Angularjs에는 ngBind, ngModel 및 ngClass와 같은 내장 구현 세트가 함께 제공되며, 생성한 컨트롤러 및 서비스와 함께 Angularjs가 부트스트랩할 때 사용할 고유한 지시문을 만들 수 있습니다. HTML 컴파일러는 DOM 요소에 해당하는 명령을 일치시키기 위해 DOM을 순회합니다.
선택기와 요소를 일치시킬 때 비슷한 용어가 사용됩니다( 요소가 선택기와 일치함) 지시문이 선언의 일부인 경우 요소가 지시문과 일치한다고 말합니다.
아래 예에서는 <input> 요소가 ngModel 지시문과 일치합니다.
AngularJS는 요소의 태그 및 속성 이름을 정규화하여 어떤 요소가 어떤 지시문과 일치하는지 결정합니다. 우리는 일반적으로 대소문자를 구분하는 camelCase 정식 이름(예: ngModel)으로 지시문을 정의(참조)합니다. 그러나 HTML은 대소문자를 구분하지 않으므로 DOM의 명령을 소문자로 참조하며 일반적으로 대시(-) 구분 기호를 사용하여 다른 단어(예: ng-model)를 구분합니다.
정규화 프로세스는 다음과 같습니다.
2. -, _, 구분자를 camelCased camelCas로 변환합니다.
예를 들어 다음 형식은 모두 동일하며 ngBind 지시어와 일치합니다.
모범 사례: 주석 및 클래스 이름보다 태그 이름 및 속성을 통해 지시문을 사용하는 것이 좋습니다. 이렇게 하면 일반적으로 특정 요소가 일치하는 지시문을 쉽게 결정할 수 있습니다.
모범 사례: 주석 지시문은 다음과 같은 곳에서 일반적으로 사용되었습니다. DOM API는 여러 요소(예:
요소 내부)에 걸쳐 있는 지시어를 생성하는 기능을 제한합니다. AngularJS 1.2에서는 이 문제에 대한 더 나은 솔루션으로 ng-repeat-start 및 ng-repeat-end를 도입합니다. 가능한 경우 사용자 지정 주석 지시문보다 이 작업을 수행합니다..지시문 만들기먼저 지시문 등록을 위한 API에 대해 논의해 보겠습니다. 컨트롤러와 마찬가지로 지시문도 모듈에 등록됩니다. 디렉티브를 등록하려면 module.directive API를 사용해야 합니다. module.directive는 표준화된 지시문 이름과 그 뒤에 팩토리 함수를 허용합니다. 이 팩토리 함수는 일치 시 어떻게 작동해야 하는지 $compile 지시문에 알려주기 위해 다양한 옵션이 있는 객체를 반환해야 합니다.
팩토리 함수는 $conpile이 처음으로 지시문과 일치할 때 한 번만 호출됩니다. 여기에서 초기화 작업을 지시할 수 있습니다. 이 (공장) 함수는 컨트롤러처럼 주입 가능하게 만드는 $injector.invoke를 사용하여 호출됩니다. 몇 가지 일반적인 지시어 예를 살펴본 다음 다양한 옵션과 컴파일 프로세스를 살펴보겠습니다.
모범 사례: 향후 표준과의 충돌을 방지하려면 자신만의 지시문 이름을 앞에 붙이는 것이 가장 좋습니다. 예를 들어 지시문을 만든 경우 HTML7에서 동일한 요소 A를 도입하면 문제가 될 수 있습니다. 2자 또는 3자 접두사(예: btfCarousel)는 잘 작동합니다. 마찬가지로 자신의 지시문에 ng를 접두사로 붙이지 마십시오. 그렇지 않으면 향후 버전의 AngularJS에 포함된 지시문과 충돌할 수 있습니다.
다음 예에서는 내 접두사(예: myCustomer). 템플릿 확장 지시어
고객 정보를 나타내는 큰 템플릿이 있다고 가정해 보겠습니다. 이 템플릿은 코드에서 여러 번 반복됩니다. 한 곳에서 변경하면 다른 여러 곳에서도 변경해야 합니다. 이는 지시문을 사용하여 템플릿을 단순화할 수 있는 좋은 기회입니다. 내용을 정적 템플릿으로 바꾸는 지시문을 만들어 보겠습니다.
이 지시문에는 바인딩이 있다는 점에 유의하세요. $compile은
를 컴파일하고 링크한 후 요소의 하위 요소에 대한 지시어를 일치시키려고 시도합니다. 이는 지시문 내에 지시문(중첩 지시문)을 작성할 수 있음을 의미합니다. 나중에 예제를 작성하는 방법을 살펴보겠습니다. 在上面的例子中,我们列出了模板选项(template attribute of return object in factory function),但随着模板大小的增长,这将变得令人讨厌。
Best Practice: Unless your template is very small, it's typically better to break it apart into its own HTML file and load it with the templateUrl option.
如果你熟悉ngInclude,templateUrl就像它一样工作。下面是使用templateUrl代替的相同示例:
templateUrl也可以是一个函数,它返回要加载和用于指令的HTML模板的URL。AngularJS将使用两个参数调用templateUrl函数:指令被调用的元素以及与该元素相关联的attr对象。
Note: You do not currently have the ability to access scope variables from the templateUrl function, since the template is requested before the scope is initialized
注:(要访问socpe上的值,应该在post-link阶段).
When should I use an attribute versus an element? Use an element when you are creating a component that is in control of the template.The common case for this is when you are creating a Domain-Specific Language for parts of your template. Use an attribute when you are decorating an existing element with new functionality.
用元素来使用myCustomer指令时明智的选择,因为你不用一些“customer”行为修饰一个元素,你定义一个元素核心行为作为一个costomer组建。(想看更多就到PHP中文网angularjs参考手册中学习)
隔离指令的Scope
我们以上的myCustomer指令很好,但是它有一个致命缺陷。我们只有在一个给定的scope下使用。
在其目前的实现上,我们应该需要去创建一些不同点控制器用来重用这个指令。
https://plnkr.co/edit/CKEgb1e...
这明显不是一个好的解决方案。
我们说项的是把指令内部的scope与外部scope(controller scope)分离,并且映射外部scope到指令内部scope。我们可以通过创建一个isolate scope来做。为此,我们可以使用指令的scope选项。
https://plnkr.co/edit/E6dTrgm...
看index.html文件,第一个元素绑定info属性值为naomi,它是我们已经暴露在我们的控制器上的scope。第二个绑定info为igor。
让我们仔细看看scope选项
//...
scope: { customerInfo: '=info' },
//...
로그인 후 복사
除了可以将不同的数据绑定到指令中的作用域外,使用isolated scope还有其他作用。
我们可以通过添加另一个属性vojta来展示,到我们的scope并尝试从我们的指令模板中访问它:
https://plnkr.co/edit/xLVqnzt...
请注意{{vojta.name}}和{{vojta.address}}为空,意味着它们未定义(undefined)。虽然我们在控制器中定义了vojta,但它在指令中不可用。
顾名思义,该指令的 isolate scope隔离了除显式添加到作用域的模型之外的所有内容:scope: {}散列对象. 这在构建可重用组件时很有用,因为它可以防止组件改变模型状态,除了显式传入。
Note: Normally, a scope prototypically inherits from its parent. An isolated scope does not. See the "Directive Definition Object - scope"section for more information about isolate scopes.
Best Practice: Use the scope option to create isolate scopes when making components that you want to reuse throughout your app.
创建一个操纵DOM的指令
在这个例子中,我们将建立一个显示当前时间的指令。每秒一次,它会更新DOM以反映当前时间。
想要修改DOM的指令通常使用link选项来注册DOM监听器以及更新DOM。它在模板被克隆之后执行,并且是放置指令逻辑的地方。
link接受一个带有一下签名的函数function link(scope, element, attrs, controller, transcludeFn) { ... }, 其中:
scope是一个Angularjs scope 对象
element 是一个此指令匹配的jqLite包装元素
attrs是一个具有标准化属性名称及其对应属性值的键值对的散列对象。
controller是指令所需的控制器实例或其自己的控制器(如果有的话)。确切的值取决于指令的 require属性。
transcludeFn是预先绑定到正确的包含范围的transclude链接函数。
For more details on the link option refer to the $compile API page.
링크 기능에서 매초 표시되는 시간을 업데이트하려고 하거나 사용자가 명령에 바인딩된 시간 형식 문자열을 변경하려고 합니다. $interval 서비스를 사용하여 핸들러를 주기적으로 호출합니다. 이는 $timeout을 사용하는 것보다 쉽지만 테스트를 완료하기 전에 모든 $timeout이 완료되었는지 확인하려는 엔드투엔드 테스트에도 더 좋습니다. 명령어가 제거되면 $interval도 제거하여 메모리 누수가 발생하지 않도록 해야 합니다.
https://plnkr.co/edit/vIhhmNp...
여기서 주의할 사항이 몇 가지 있습니다. module.controller API와 마찬가지로 module.directive의 함수 매개변수는 종속성이 주입됩니다. 따라서 지시문의 링크 함수에서 $interval 및 dateFilter를 사용할 수 있습니다.
이벤트 요소를 등록합니다.on('$destroy', ...). 이 $destroy 이벤트를 유발하는 요인은 무엇입니까?
AngularJS는 몇 가지 특별 이벤트를 게시합니다. AngularJS 컴파일러로 컴파일된 DOM 노드가 삭제되면 $destroy 이벤트가 발생합니다. 마찬가지로 Angularjs 범위가 소멸되면 $destroy 이벤트를 수신 범위에 브로드캐스트합니다.
이 이벤트를 청취함으로써 메모리 누수를 일으킬 수 있는 이벤트 리스너를 제거할 수 있습니다. 범위와 요소에 등록된 리스닝 이벤트는 DOM이 소멸되면 자동으로 정리되지만, 서비스에 리스너를 등록했거나 삭제되지 않은 DOM 노드에 리스너를 등록한 경우 직접 정리해야 합니다. 그렇지 않으면 메모리 누수가 발생할 위험이 있습니다.
모범 사례: 지시문은 자체적으로 정리해야 합니다. element.on('$destroy', ...) 또는scope.$on('$destroy', ...)을 사용하여 정리를 실행할 수 있습니다.
다른 요소를 래핑하는 지시문 만들기
격리 범위를 사용하여 모델을 지시문에 전달할 수 있지만 때로는 대신 전체 템플릿을 전달하고 싶을 때도 있습니다. 문자열 또는 객체. "대화 상자" 구성 요소를 만들고 싶다고 가정하겠습니다. 대화 상자에는 임의의 콘텐츠를 래핑할 수 있는 기능이 있어야 합니다.
이를 위해서는 transclude 옵션을 사용해야 합니다.
transclude 옵션의 역할은 정확히 무엇인가요? transclude는 이 옵션을 통해 내부 범위가 아닌 외부 지시문의 범위에서 지시문의 내용에 액세스할 수 있도록 합니다.
이 점을 설명하려면 아래 예를 참조하세요. script.js에 링크 함수를 추가하여 이름을 Jeff로 재정의했습니다. {{name}} 바인딩이 무엇을 달성할 것이라고 생각하시나요?
늘 그렇듯이 우리는 {{name}}이(가) Jeff여야 한다고 생각했습니다. 그러나 우리가 보는 것은 토비아스입니다.
transclude 옵션은 범위가 중첩되는 방식을 변경합니다. 이로 인해 삽입된 지시어의 내용은 내부 범위가 아닌 지시어 외부의 범위 내용을 갖게 됩니다. 이렇게 하면 외부 범위에서 콘텐츠에 액세스할 수 있게 됩니다.
지시문이 자체 독립 범위를 생성하지 않는 경우,scope.name = 'Jeff'의 범위는 외부 범위를 참조하고 출력에서 Jeff를 볼 수 있습니다.
이 동작은 무언가를 캡슐화하는 지시문에 적합합니다. 그렇지 않으면 사용하려는 각 모델을 별도로 전달해야 하기 때문입니다. 원하는 모든 모델을 전달해야 한다면 실제로 임의의 콘텐츠를 사용할 수 없습니다. 그렇죠?
모범 사례: 임의의 콘텐츠를 래핑하는 지시어를 만들려면 transclude: true만 사용하세요.
다음으로 이 대화 상자에 버튼을 추가하고 지시어를 사용하는 사용자가 동작을 변경할 수 있도록 허용하겠습니다. 이 대화 상자에.
지시문의 범위에서 호출하여 전달한 함수를 실행하고 싶지만 등록된 범위의 컨텍스트에서 실행됩니다.
범위 옵션에서 =attr을 사용하는 방법을 이전에 살펴봤지만 위의 예에서는 대신 &attr을 사용했습니다. & 바인딩을 사용하면 지시문이 특정 시점에 기본 범위 내에서 표현식 평가를 트리거할 수 있습니다. 함수 호출이 포함된 표현을 포함하여 모든 법적 표현이 허용됩니다. 따라서 & 바인딩은 콜백 함수를 지시문 작업에 바인딩하는 데 이상적입니다.
사용자가 대화 상자에서 x를 클릭하면 ng-click 덕분에 지시문의 닫기 기능이 호출됩니다. 격리된 범위에 대한 이 닫기 호출은 실제로 원래 범위의 컨텍스트에서 hideDialog(message) 표현식을 평가하여 컨트롤러의 hideDialog 함수가 실행되도록 합니다.
일반적으로 표현식을 통해 격리 범위에서 상위 범위로 데이터를 전달하는 것으로 예상됩니다. 이는 지역 변수 이름과 값의 맵을 표현식 래퍼 함수에 전달하여 수행할 수 있습니다. 예를 들어, hideDialkog 함수는 대화 상자가 숨겨질 때 표시할 메시지를 허용합니다. 이는 close({message: 'closing for now'}) 지시문 호출로 표시됩니다. 그런 다음 on-close 표현식 내에서 지역 변수 메시지에 액세스(사용 가능)됩니다.
모범 사례: 지시어가 동작에 바인딩하기 위해 API를 노출하도록 하려면 범위 옵션에서 &attr을 사용하세요.
하나 만들기 이벤트 리스너를 추가하는 지시문
이전에는 링크 함수를 사용하여 DOM 요소를 조작하는 지시문을 만들었습니다. 이 예제를 바탕으로 해당 요소의 이벤트에 반응하는 지시문을 만들어 보겠습니다.
예를 들어, 사용자가 요소를 드래그할 수 있는 지시어를 생성하려면 어떻게 해야 할까요?
创建一个通信的指令
你可以组建任何指令通过模板使用他们。
有时,你需要一个由指令组合构建的组件。
想象你想要有一个容器,其中容器的内容对应于哪个选项卡处于活动状态的选项卡。
myPane指令有require选项值为^^myTabs. 当指令使用此选项,&compile将抛出一个错误除非特定的controller被找到。 ^^前缀表示该指令在其父元素上搜索控制器。(^前缀将使指令在自身元素或她的父元素上寻找控制器;又没任何前缀,指令将值操作自身)
所以这个myTabs contoller从哪里来的?指令可以特定一个controllers通过使用 controller选项。如你所见,myTabs指令使用了此选项。就像ngController,此选项附加一个控制器到指令的模板上。
如果需要从模板中引用控制器或绑定到控制器的任何功能,则可以使用选项controllerAs将控制器的名称指定为别名。该指令需要定义要使用的此配置的范围。这在指令被用作组件的情况下特别有用。
回头看myPane的定义,注意到link函数的最后一个参数:tabCtrl。当指令需要控制器时,它将接收该控制器作为其link函数的第四个参数。利用这一点,myPane可以调用myTabs的addPane函数。
如果需要多个控制器,则指令的require选项可以采用数组参数。发送给链接函数的相应参数也将是一个数组。
angular.module('docsTabsExample', [])
.directive('myPane', function() {
return {
require: ['^^myTabs', 'ngModel'],
restrict: 'E',
transclude: true,
scope: {
title: '@'
},
link: function(scope, element, attrs, controllers) {
var tabsCtrl = controllers[0],
modelCtrl = controllers[1];
tabsCtrl.addPane(scope);
},
templateUrl: 'my-pane.html'
};
});
로그인 후 복사
明的读者可能想知道链接和控制器之间的区别。基本的区别是控制器可以暴露一个API,并且链接函数可以使用require与控制器交互。
Best Practice: use controller when you want to expose an API to other directives. Otherwise use link.
总结
到此我们已经看了大多数指令的用法,每一个样例演示了一个创建你自己指令的好的起始点。
你可能深入感兴趣于编译过程的解释可以在这里获得compiler guide.
$compile API 有一个全面的指令清单选项以供参考。
最后就是本篇文章到这结束了(想看更多就到PHP中文网angularjs学习手册中学习),有问题的可以在下方留言提问
위 내용은 Anglejs에서 사용자 정의 지시문을 만드는 방법은 무엇입니까? Anglejs를 사용하여 사용자 정의 지침을 생성하는 세부 프로세스의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!