> 웹 프론트엔드 > JS 튜토리얼 > Angular의 Directive 사용법에 대한 심층 분석

Angular의 Directive 사용법에 대한 심층 분석

青灯夜游
풀어 주다: 2021-04-13 10:45:36
앞으로
2420명이 탐색했습니다.

이 글에서는 Angular 지시문을 자세히 소개하고 사용법을 이해해보겠습니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.

Angular의 Directive 사용법에 대한 심층 분석

Angular 지시어 학습

학습 목적: ng 지시어 사용 방법을 더 잘 이해합니다.

Directive는 AngularJS에서 더 복잡할 수 있습니다. 일반적으로 우리는 그것을 지시로 이해합니다. AngularJS에는 ng-app, ng-controller 등과 같은 많은 사전 설정 지침이 함께 제공됩니다. AngularJS와 함께 제공되는 지침은 모두 ng-로 시작하는 특징을 찾을 수 있습니다.

그럼 Directive란 정확히 무엇인가요? 내 개인적인 이해는 HTML과 JS 조각을 함께 캡슐화하여 특정 기능을 갖춘 재사용 가능한 독립 엔터티를 형성한다는 것입니다. Directive의 일반적인 사용법을 자세히 설명하겠습니다.

AnguarJS 지시문의 공통 정의 형식 및 매개변수 설명

아래 코드를 살펴보세요.

var myDirective = angular.module('directives', []);

myDirective.directive('directiveName', function($inject) {
    return {
        template: '<div></div>',
        replace: false,
        transclude: true,
        restrict: 'E',
        scope: {},
        controller: function($scope, $element) {

        },
        complie: function(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {

                },
                post: function postLink(scope, iElement, iAttrs, controller) {

                }
            };
        },
        link: function(scope, iElement, iAttrs) {

        }
    };
});
로그인 후 복사
  • 객체는 여기에 직접 반환되며 객체에는 많은 속성이 포함되어 있으며 이는 모두 사용자 정의 지시어의 정의입니다. 자세한 의미는 아래에서 설명하겠습니다.
  • 반환 객체 매개변수 설명
return {
    name: '',
    priority: 0,
    terminal: true,
    scope: {},
    controller: fn,
    require: fn,
    restrict: '',
    template: '',
    templateUrl: '',
    replace: '',
    transclude: true,
    compile: fn,
    link: fn
}
로그인 후 복사

추천 관련 튜토리얼: "angular tutorial"

위에 표시된 것처럼 반환 객체에는 많은 속성이 있으며 이 속성 줄은 지시어를 정의하는 데 사용됩니다.

그 기능을 하나씩 설명해 보겠습니다.

  • namename

    • 表示当前scope的名称,一般声明时使用默认值,不用手动设置此属性。
  • priority

    • 优先级。当有多个directive定义在同一个DOM元素上时,有时需要明确他们的执行顺序。这个属性用于在directive的compile function调用之前进行排序。如果优先级相同,则执行顺序是不确定的(根据经验,优先级高的先执行,相同优先级时按照先绑定后执行)。
  • teminal

    • 最后一组。如果设置为true,则表示当前的priority将会成为最后一组执行的directive,即比此directive的priority更低的directive将不会执行。同优先级依然会执行,但是顺序不确定。
  • scope

    • true
      • 将为这个directive创建一个新的scope。如果在同一个元素中有多个directive需要新的scope的话,它还是只会创建一个scope。新的作用域规则不适用于根模版,因为根模版往往会获得一个新的scope。
    • {}
      • 将创建一个新的、独立的scope,此scope与一般的scope的区别在于它不是通过原型继承于父scope的。这对于创建可复用的组件是很有帮助的,可以有效的防止读取或者修改父级scope的数据。这个独立的scope会创建一个拥有一组来源于父scope的本地scope属性hash集合。这些本地scope属性对于模版创建值的别名很有帮助。本地的定义是对其来源的一组本地scope property的hash映射。
  • controller

    • controller构造函数。controller会在pre-linking步骤之前进行初始化,并允许其他directive通过指定名称的require进行共享。这将允许directive之间相互沟通,增强相互之间的行为。controller默认注入了以下本地对象:
      • $scope 与当前元素结合的scope
      • $element 当前的元素
      • $attrs 当前元素的属性对象
      • $transclude 一个预先绑定到当前scope的转置linking function
  • require

    • 请求另外的controller,传入当前directive的linking function中。require需要传入一个directive controller的名称。如果找不到这个名称对应的controller,那么将会抛出一个error。名称可以加入以下前缀:
      • ? 不要抛出异常。这将使得这个依赖变为一个可选项
      • ^ 允许查找父元素的controller
  • restrict

    • EACM的子集的字符串,它限制了directive为指定的声明方式。如果省略的话,directive将仅仅允许通过属性声明
      • E 元素名称:
      • A 属性名:
      • C class名:
      • M 注释:
  • template

    • 如果replace为true,则将模版内容替换当前的html元素,并将原来元素的属性、class一并转移;如果replace为false,则将模版元素当作当前元素的子元素处理。
  • templateUrl

    🎜은 현재 범위의 이름을 나타냅니다. 일반적으로 선언 시 기본값이 사용되며 이 속성을 수동으로 설정할 필요가 없습니다. 🎜🎜🎜🎜🎜우선순위🎜🎜🎜우선순위. 동일한 DOM 요소에 여러 지시문이 정의된 경우 실행 순서를 지정해야 하는 경우가 있습니다. 이 속성은 지시문의 컴파일 기능이 호출되기 전에 정렬하는 데 사용됩니다. 우선순위가 동일하면 실행 순서가 불확실하다(경험에 따르면 우선순위가 높은 것이 먼저 실행되고, 우선순위가 동일하면 먼저 바인딩된 후 실행된다). 🎜🎜🎜🎜🎜terminal🎜🎜🎜마지막 그룹입니다. true로 설정하면 현재 우선순위가 실행될 마지막 지시문 그룹이 된다는 의미입니다. 즉, 이 지시문보다 우선순위가 낮은 지시문은 실행되지 않습니다. 동일한 우선순위가 계속 실행되지만 순서는 불확실합니다. 🎜🎜🎜🎜🎜scope🎜🎜🎜true🎜🎜는 이 지시어에 대한 새로운 범위를 생성합니다. 동일한 요소에 새 범위가 필요한 여러 지시문이 있는 경우에도 여전히 하나의 범위만 생성됩니다. 루트 템플릿은 새로운 범위를 얻는 경향이 있기 때문에 새로운 범위 지정 규칙은 루트 템플릿에 적용되지 않습니다. 🎜🎜🎜🎜{}🎜🎜는 새로운 독립 범위를 생성합니다. 이 범위와 일반 범위의 차이점은 프로토타입을 통해 상위 범위에서 상속되지 않는다는 것입니다. 이는 재사용 가능한 구성 요소를 만드는 데 도움이 되며 상위 범위의 데이터를 읽거나 수정하는 것을 효과적으로 방지할 수 있습니다. 이 독립 범위는 상위 범위에서 파생된 로컬 범위 속성 집합을 사용하여 해시 집합을 만듭니다. 이러한 로컬 범위 속성은 템플릿이 값에 대한 별칭을 만드는 데 유용합니다. 로컬의 정의는 로컬 범위 속성 집합을 소스에 대한 해시 매핑입니다. 🎜🎜🎜🎜🎜🎜🎜컨트롤러🎜🎜🎜컨트롤러 생성자. 컨트롤러는 사전 연결 단계 전에 초기화되며 지정된 이름을 사용하여 요구 사항을 통해 다른 지시문을 공유할 수 있습니다. 이를 통해 지시문이 서로 통신하고 서로의 동작을 향상시킬 수 있습니다. 컨트롤러는 기본적으로 다음 로컬 개체를 주입합니다. 🎜🎜$scope 현재 요소와 결합된 범위 🎜🎜$element 현재 요소 🎜🎜$attrs 현재 요소의 속성 개체 🎜🎜$transclude 사전 바인딩된 전치된 연결 함수 현재 범위로 🎜🎜🎜🎜🎜🎜🎜require🎜🎜🎜다른 컨트롤러를 요청하고 이를 현재 지시어의 연결 함수에 전달합니다. require는 지시문 컨트롤러의 이름을 전달해야 합니다. 이 이름에 해당하는 컨트롤러를 찾을 수 없으면 오류가 발생합니다. 이름 앞에 다음이 붙을 수 있습니다. 🎜🎜 예외를 발생시키지 마세요. 이렇게 하면 이 종속성이 부모 요소 컨트롤러 🎜🎜🎜🎜🎜🎜🎜restrict🎜🎜🎜EACM의 하위 집합을 검색할 수 있는 선택적 🎜🎜^ 문자열이 되어 지시문을 지정된 선언 방법으로 제한합니다. . 생략하면 지시어는 속성을 통한 선언만 허용합니다. 🎜🎜E 요소 이름: 🎜🎜A 속성 이름: 🎜🎜C 클래스 이름: 🎜🎜M 댓글: 🎜🎜🎜🎜🎜🎜🎜template🎜 🎜🎜replace가 true인 경우 템플릿 콘텐츠는 현재 html 요소를 대체하고 원본 요소의 속성과 클래스는 함께 전송됩니다. replacement가 false인 경우 템플릿 요소는 현재 요소의 하위 요소로 처리됩니다. . 🎜🎜🎜🎜🎜templateUrl🎜
    • 与template基本一致,但模版通过指定的url进行加载。因为模版加载是异步的,所有compilation、linking都会暂停,等待加载完毕后再执行。
  • replace

    • 如果设置为true,那么模版将会替换当前元素,而不是作为子元素添加到当前元素中。(为true时,模版必须有一个根节点)
  • transclude

    • 编译元素的内容,使它能够被directive使用。需要在模版中配合ngTransclude使用。transclusion的有点是linking function能够得到一个预先与当前scope绑定的transclusion function。一般地,建立一个widget,创建独立scope,transclusion不是子级的,而是独立scope的兄弟级。这将使得widget拥有私有的状态,transclusion会被绑定到父级scope中。(上面那段话没看懂。但实际实验中,如果通过调用myDirective,而transclude设置为true或者字符串且template中包含的时候,将会将的编译结果插入到sometag的内容中。如果any的内容没有被标签包裹,那么结果sometag中将会多了一个span。如果本来有其他东西包裹的话,将维持原状。但如果transclude设置为’element’的话,any的整体内容会出现在sometag中,且被p包裹)
      • true/false 转换这个directive的内容。(这个感觉上,是直接将内容编译后搬入指定地方)
      • ‘element’ 转换整个元素,包括其他优先级较低的directive。(像将整体内容编译后,当作一个整体(外面再包裹p),插入到指定地方)
  • compile

    • 这里是compile function,将在下面实例详细说明
  • link

    • 这里是link function ,将在下面实例详细讲解。这个属性仅仅是在compile属性没有定义的情况下使用。

关于scope

这里关于directive的scope为一个object时,有更多的内容非常有必要说明一下。看下面的代码:

scope: {
    name: '=',
    age: '=',
    sex: '@',
    say: '&'
}
로그인 후 복사

这个scope中关于各种属性的配置出现了一些奇怪的前缀符号,有=,@,&,那么这些符号具体的含义是什么呢?再看下面的代码:

  • html
<div my-directive name="myName" age="myAge" sex="male" say="say()"></div>复制代码
로그인 후 복사
  • javascript
function Controller($scope) {
    $scope.name = 'Pajjket';
    $scope.age = 99;
    $scope.sex = '我是男的';
    $scope.say = function() {
        alert('Hello,我是弹出消息');
    };
}
로그인 후 복사
可以看出,几种修饰前缀符的大概含义:
  • =: 指令中的属性取值为Controller中对应$scope上属性的取值
  • @: 指令中的取值为html中的字面量/直接量
  • &: 指令中的取值为Controller中对应$scope上的属性,但是这个属性必须为一个函数回调 下面是更加官方的解释:
  • =或者=expression/attr

在本地scope属性与parent scope属性之间设置双向的绑定。如果没有指定attr名称,那么本地名称将与属性名称一致。

  • 例如: 中,widget定义的scope为:{localModel: '=myAttr'},那么widget scope property中的localName将会映射父scope的parentModel。如果parentModel发生任何改变,localModel也会发生改变,反之亦然。即双向绑定。

  • @或者@attr 建立一个local scope property到DOM属性的绑定。因为属性值总是String类型,所以这个值总返回一个字符串。如果没有通过@attr指定属性名称,那么本地名称将与DOM属性的名称一致。 例如: ,widget的scope定义为:{localName: '@myAttr'}。那么,widget scope property的localName会映射出"hello "转换后的真实值。当name属性值发生改变后,widget scope的localName属性也会相应的改变(仅仅是单向,与上面的=不同)。那么属性是在父scope读取的(不是从组件的scope读取的)

  • &或者&attr 提供一个在父scope上下文中执行一个表达式的途径。如果没有指定attr的名称,那么local name将与属性名一致。

    • 例如:

<widget my-attr="count = count + value">,widget的scope定义为:{localFn:’increment()’},那么isolate scope property localFn会指向一个包裹着increment()表达式的function。 一般来说,我们希望通过一个表达式,将数据从isolate scope传到parent scope中。这可以通过传送一个本地变量键值的映射到表达式的wrapper函数中来完成。例如,如果表达式是increment(amount),那么我们可以通过localFn({amount:22})的方式调用localFn以指定amount的值。

directive 实例讲解

下面的示例都围绕着上面所作的参数说明而展开的。

  • directive声明实例
// 自定义directive
var myDirective = angular.modeule(&amp;#39;directives&amp;#39;, []);

myDirective.directive(&amp;#39;myTest&amp;#39;, function() {
    return {
        restrict: &amp;#39;EMAC&amp;#39;,
        require: &amp;#39;^ngModel&amp;#39;,
        scope: {
            ngModel: &amp;#39;=&amp;#39;
        },
        template: &amp;#39;&lt;div&gt;&lt;h4&gt;Weather for {{ngModel}}&lt;/h4&lt;/div&gt;&amp;#39;
    };
});

// 定义controller
var myControllers = angular.module(&amp;#39;controllers&amp;#39;, []);
myControllers.controller(&amp;#39;testController&amp;#39;, [
    &amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.name = &amp;#39;this is directive1&amp;#39;;
    }
]);


var app = angular.module(&amp;#39;testApp&amp;#39;, [
    &amp;#39;directives&amp;#39;,
    &amp;#39;controllers&amp;#39;
]);

&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;testController&quot;&gt;
        &lt;input type=&quot;text&quot; ng-model=&quot;city&quot; placeholder=&quot;Enter a city&quot; /&gt;
        &lt;my-test ng-model=&quot;city&quot; &gt;&lt;/my-test&gt;
        &lt;span my-test=&quot;exp&quot; ng-model=&quot;city&quot;&gt;&lt;/span&gt;
        &lt;span ng-model=&quot;city&quot;&gt;&lt;/span&gt;
    &lt;/div&gt;
&lt;/body&gt;
로그인 후 복사

template与templateUrl的区别和联系

templateUrl其实根template功能是一样的,只不过templateUrl加载一个html文件,上例中,我们也能发现问题,template后面根的是html的标签,如果标签很多呢,那就比较不爽了。可以将上例中的,template改一下。

myDirective.directive(&amp;#39;myTest&amp;#39;, function() {
    return {
        restrict: &amp;#39;EMAC&amp;#39;,
        require: &amp;#39;^ngModel&amp;#39;,
        scope: {
            ngModel: &amp;#39;=&amp;#39;
        },
        templateUrl:&amp;#39;../partials/tem1.html&amp;#39;   //tem1.html中的内容就是上例中template的内容。
    }
});
로그인 후 복사

scope重定义

//directives.js中定义myAttr
myDirectives.directive(&amp;#39;myAttr&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        scope: {
            customerInfo: &amp;#39;=info&amp;#39;
        },
        template: &amp;#39;Name: {{customerInfo.name}} Address: {{customerInfo.address}}&lt;br&gt;&amp;#39; +
                  &amp;#39;Name: {{vojta.name}} Address: {{vojta.address}}&amp;#39;
    };
});

//controller.js中定义attrtest
myControllers.controller(&amp;#39;attrtest&amp;#39;,[&amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.naomi = {
            name: &amp;#39;Naomi&amp;#39;,
            address: &amp;#39;1600 Amphitheatre&amp;#39;
        };
        $scope.vojta = {
            name: &amp;#39;Vojta&amp;#39;,
            address: &amp;#39;3456 Somewhere Else&amp;#39;
        };
    }
]);

// html中
&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;attrtest&quot;&gt;
        &lt;my-attr info=&quot;naomi&quot;&gt;&lt;/my-attr&gt;
    &lt;/div&gt;
&lt;/body&gt;
로그인 후 복사

其运行结果如下:

Name: Naomi Address: 1600 Amphitheatre      //有值,因为customerInfo定义过的
Name: Address:                              //没值 ,因为scope重定义后,vojta是没有定义的
로그인 후 복사

我们将上面的directive简单的改一下,

myDirectives.directive(&amp;#39;myAttr&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        template: &amp;#39;Name: {{customerInfo.name}} Address: {{customerInfo.address}}&lt;br&gt;&amp;#39; +
                  &amp;#39;Name: {{vojta.name}} Address: {{vojta.address}}&amp;#39;
    };
});
로그인 후 복사
  • 运行结果如下:
Name: Address:
Name: Vojta Address: 3456 Somewhere Else
로그인 후 복사

因为此时的directive没有定义独立的scope,customerInfo是undefined,所以结果正好与上面相反。

transclude的使用

  • transclude的用法,有点像jquery里面的$().html()功能
myDirective.directive(&amp;#39;myEvent&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        transclude: true,
        scope: {
            &amp;#39;close&amp;#39;: &amp;#39;$onClick&amp;#39;      //根html中的on-click=&quot;hideDialog()&quot;有关联关系
        },
        templateUrl: &amp;#39;../partials/event_part.html&amp;#39;
    };
});

myController.controller(&amp;#39;eventTest&amp;#39;, [
    &amp;#39;$scope&amp;#39;,
    &amp;#39;$timeout&amp;#39;,
    function($scope, $timeout) {
        $scope.name = &amp;#39;Tobias&amp;#39;;
        $scope.hideDialog = function() {
            $scope.dialogIsHidden = true;
            $timeout(function() {
                $scope.dialogIsHidden = false;
            }, 2000);
        };
    }
]);
로그인 후 복사
&lt;body ng-app=&quot;phonecatApp&quot;&gt;
    &lt;div ng-controller=&quot;eventtest&quot;&gt;
        &lt;my-event ng-hide=&quot;dialogIsHidden&quot; on-click=&quot;hideDialog()&quot;&gt;
            Check out the contents, {{name}}!
        &lt;/my-event&gt;
    &lt;/div&gt;
&lt;/body&gt;

&lt;!--event_part.html --&gt;
&lt;div&gt;
    &lt;a href ng-click=&quot;close()&quot;&gt;×&lt;/a&gt;
    &lt;div ng-transclude&gt;&lt;/div&gt;
&lt;/div&gt;
로그인 후 복사
  • 说明:这段html最终的结构应该如下所示:
&lt;body ng-app=&quot;phonecatApp&quot;&gt;
    &lt;div ng-controller=&quot;eventtest&quot;&gt;
        &lt;div ng-hide=&quot;dialogIsHidden&quot; on-click=&quot;hideDialog()&quot;&gt;
            &lt;span&gt;Check out the contents, {{name}}!&lt;/span&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
로그인 후 복사
  • 将原来的html元素中的元素Check out the contents, !插入到模版的中,还会另外附加一个标签。controllerlinkcompile之间的关系
myDirective.directive(&amp;#39;exampleDirective&amp;#39;, function() {
    return {
        restrict: &amp;#39;E&amp;#39;,
        template: &amp;#39;&lt;p&gt;Hello {{number}}!&lt;/p&gt;&amp;#39;,
        controller: function($scope, $element){
            $scope.number = $scope.number + &quot;22222 &quot;;
        },
        link: function(scope, el, attr) {
            scope.number = scope.number + &quot;33333 &quot;;
        },
        compile: function(element, attributes) {
            return {
                pre: function preLink(scope, element, attributes) {
                    scope.number = scope.number + &quot;44444 &quot;;
                },
                post: function postLink(scope, element, attributes) {
                    scope.number = scope.number + &quot;55555 &quot;;
                }
            };
        }
    }
});

//controller.js添加
myController.controller(&amp;#39;directive2&amp;#39;,[
    &amp;#39;$scope&amp;#39;,
    function($scope) {
        $scope.number = &amp;#39;1111 &amp;#39;;
    }
]);

//html
&lt;body ng-app=&quot;testApp&quot;&gt;
    &lt;div ng-controller=&quot;directive2&quot;&gt;
        &lt;example-directive&gt;&lt;/example-directive&gt;
    &lt;/div&gt;
&lt;/body&gt;
로그인 후 복사
  • 上面小例子的运行结果如下:
Hello 1111 22222 44444 5555 !
로그인 후 복사

由结果可以看出来,controller先运行,compile后运行,link不运行。 我们现在将compile属性注释掉后,得到的运行结果如下:Hello 1111 22222 33333 !

由结果可以看出来,controller先运行,link后运行,link和compile不兼容。一般地,compile比link的优先级要高。

更多编程相关知识,请访问:编程入门!!

위 내용은 Angular의 Directive 사용법에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿