11 Detailed instructions

Instruction details

Directives are some custom tags attached to HTML elements (for example: attributes, elements, or css classes) that tell the AngularJS HTML compiler ( $compile) to attach some specified behavior to the element, even manipulate the DOM, change DOM elements , and its child nodes at all levels.

Accessing the DOM through custom directives: With Angular, the only place in a program that is allowed to touch the DOM is "directives". This is required because code that requires access to the DOM is difficult to automate testing. If you need direct access to the DOM, then you should write a custom directive for that.

The life cycle of an instruction begins with the $compilemethod and ends with the link method.

matching of instructions

Angular normalizes an element's tag and attribute names to determine which element matches which directive. We usually use case-sensitive canonical naming - camel case - (such as ngModel ) to identify directives. However, HTML is case-sensitive, so the directives we use in the DOM can only be named in lowercase, usually separated by dashes (eg: ng-model).

That is, use camelCase to name an instruction, runoobDirective, but use it with a --split, runoob-directive.

$compile(编译)Directives can be matched based on element names, attributes, class names, and comments. All directives provided by Angular support the form of element names, attributes, class names and comments.

Detailed explanation of Module.directive

grammar:Module.directive(name,directiveFactory);

Calling this method indicates that this module will $compileProviderregister a directive in

parameter:

  • name: command name.
  • directiveFactory: Directive constructor.

module.directive accepts normalized directive names and factory methods. The factory method should return an object with various options to tell the compiler $compilewhat to do when the directive is matched.

The factory function is only called once when the compiler matches the instruction for the first time. You can do the initialization work here. The function uses $injector.invokecall, so it can do dependency injection like a controller.

module.directive returns another directive function with a return statement, and with this custom directive, Angular will call this function.

The directive function accepts three parameters, the first scope, which is used to inspect the data available in the view. The second parameter element is a jqLite object, jqLite is a tailored version of jQuery provided by Angular. The third parameter is attrs.

The object defined by the directive provides a description for the compiler, and its properties are:

  • priority:Number

    When there are multiple directives defined in a DOM element, it is sometimes necessary to specify the order in which the directives are applied. Compile functions are prioritized before being called. The larger the value of this property, the higher the priority and will be compiled first. The order of instructions with the same priority is undefined. The default priority is 0.

  • terminal: Boolean

    If this property is set to true, then the priority of the current instruction will be placed in the last group to be executed (any instructions at the current priority will still be executed as the undefined priority setting)

  • scope:Boolean or Object

    • If set to false, no scope will be created for the directive. Directives use their parent's scope.
    • If set to true, the directive will create a new child scope that inherits the parent's properties. If a new scope is defined on multiple directives in a DOM, only one new scope can be created. After a template has a new scope, the rules of the scope do not apply to the root node where the template is located.
    • If set to {}, then a new, isolated scope will be created. The scope does not inherit from its parent scope, so that it does not affect the parent scope's data when creating reusable directives.
      This isolated scope will have a set of objects consisting of data from the parent scope, whose names are prefixed with:
      • @ or @attr : The attribute value on the DOM element combined with the locally scoped attribute. Binding as string type on DOM elements and in directive scope. If no name is specified, it is the same as the name assumed to be in the directive scope.
      • = or =attr: Set up two-way binding of data between directive scope and parent scope. If no name is specified, it is the same as the name assumed to be in the directive scope.
      • & or &attr: Provides an expression to be executed in the context of the parent scope.
  • controller:String orfunction(scope, element, attrs, transclude, otherInjectables) { ... }

    The controller constructor for this directive. The controller will be instantiated before precompiling and can be shared with other directives (see the require attribute). This enables communication between instructions, enhancing the behavior of each other. The following parameters can be written:

    • $scope: The current scope associated with the element.
    • $element: The current element.
    • $attr: The attribute on the current element.
    • $transclude: A linking function that is pre-bound to the correct embedded scope. The range can be overridden by a first optional parameter. function([scope], cloneLinkingFn).
  • require:String

    Requires another directive and injects its controller into the linking function as the fourth parameter. Needs to be injected with the string name (or array of strings) of the directive. If an array is used, the injected parameter will be the corresponding order in an array. If no such instruction is found, or if the instruction has no controller, an error will occur. The property name is prefixed with:

    • No prefix: The controller required to locate the current element. If no errors are found, throw an error.
    • ? : Attempts to find the desired controller, if not found, through the empty function.
    • ^: Find the desired controller by searching the element's parent node, and throw an error if not found.
  • controllerAs:String

    The alias for the controller in the directive scope. An alias for the controller to reference in this directive template. The directive requires this configuration to be defined in the applicable scope. Useful when directives are used as components.

  • restrict:String

    A subset of EACM that restricts declarative directives to a specific directive.

    • E: element name,<my-directive></my-directive>
    • A: element attribute,<div my-directive="exp"></div>
    • C: Element class:<div class="my-directive: exp;"></div>
    • M: Notes,<!-- directive: my-directive exp -->
  • template:String or Template Function

    Replaces the current element with a directive block of HTML content. The process will update all attributes/classes of the previous old element on the new element. This attribute can specify the template as a string or a function template, takes two parameters tElement and tAttrs, and returns a string value representing the template.

  • templateUrl: String

    Basically the same as template, but the template is loaded via the specified url. Because the template is loaded asynchronously, both the complie and the link will be occupied, waiting for the template to be loaded.

  • replace: Boolean or String

Specifies where to insert the module, defaults to false.

* true:模板将会替换当前元素。
* false:模板将会替换当前元素的内容。
  • transclude:Boolean

    Compile the content of the element and make it available within the directive. This allows the component to have private state and the embedded part to be included in the parent scope.

    • true: The directive can embed content.
    • false: Embeds the entire unit including any directives defined at lower priority.
  • compile

    function(tElement, tAttrs, transclude) {
    return {
    pre: function(scope, iElement, iAttrs, controller) { ... },
    post: function(scope, iElement, iAttrs, controller) { ... }
    }
    // 或者
    // return function postLink(...) { ... }
    }

    The compile function assigns the transformation of the template. Since most directives don't do template conversion, it's not used very often. Examples that require compile to transform templates are ngRepeat, or asynchronously loading content, such as ngView. Compilation requires the following parameters:

    • tElement: Template element, the element that this directive has declared. It is only safe to do template transformations on elements and child elements.
    • tAttr: Template attribute, shared between all directive compile functions.
    • transclude: a transclude linking function – function(scope, cloneLinkingFn)
      Note: If the template is cloned, the template instance and the link instance are different objects. Therefore, all DOM nodes cloned in the compile function are unsafe for DOM transformation. Specifically, DOM monitoring should be in the link function instead of the compile function.
      Note: The compile function cannot manipulate directives to recursively use its own template or compile function. Compiling these instructions will result in an infinite loop and stack overflow error. Instead of relying on manual compilation of templates via template or templateUrl or in the compile function, the template can be forced manually using the postLink function.
  • link

    This property is used if the compile property is not defined.

    function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }

    The link function is responsible for registering DOM listeners and updating DOM operations. This function is executed after the template is cloned. Most of the instruction logic is placed here.

    Function parameters:

    * scope:被注册监听的指令使用的作用域。
    * iElement:元素实例,使用该指令的元素。当子元素已被关联,那么只能在postLink函数内操作是安全的。
    * iAttrs:属性实例,在这个元素上声明的属性,在所有指令的linking函数内共享。
    * controller:如果至少有一个指令的元素定义一个控制器,那么是个控制器实例。控制器在所有的指令中被共享,它允许指令使用控制器作为通信通道。
    * transcludeFn:预绑定到正确的嵌入范围的一个linking函数。范围可以通过一个可选的第一个参数重写--function([scope], cloneLinkingFn)
    
  • pre-linking function: Executed before associating child elements.

  • Post-linking function: Executed after associating child elements.

Directive isolation scope binding strategy

In order for the new directive scope to access variables in the current local scope, one of the following three aliases needs to be used.

  • Local scope property: Use the @symbol ( @ (or @attr)) to bind the local scope to the value of the DOM property. Directive inner scopes can use variables from outer scopes.
  • Two-way binding: Through = ( = (or =attr)), two-way data binding can be performed between the properties on the local scope and the properties on the parent scope. Just like normal data binding, local properties reflect changes in the parent data model.

  • Parent scope binding: The &symbol ( & (or &attr)) allows you to bind the parent scope to run functions in it. Means that setting this value will generate a wrapper function that points to the parent scope. To call the parent method with one parameter, we need to pass an object whose key is the name of the parameter and the value is what to pass to the parameter.

For example, let's say we're developing an email client and want to create a text input box for email:

<input type="text" ng-model="to"/>
<!-- 调用指令 -->
<div scope-example ng-model="to"
on-send="sendMail(email)"
from-name="[email protected]" />
scope: {
ngModel: '=', // 将ngModel同指定对象绑定
onSend: '&', // 将引用传递给这个方法
fromName: '@' // 储存与fromName相关联的字符串
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="../../css/bootstrap.css" rel="stylesheet">
<script src="../../script/angular.min.js"></script>
<script>
var m= angular.module("my", [])
m.controller("ctr1", function ($scope) {
$scope.dayNames = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
$scope.today = $scope.dayNames[new Date().getDay()];
//getDay星期是从0开始的,星期日的下标是0
});
m.controller("ctr2", function ($scope) {
$scope.dayNames = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
$scope.tommorrow = $scope.dayNames[(new Date().getDay() + 1) % 7];
});
m.directive('highlight', function () {
return function (scope,element,attrs) {
if(scope.today == attrs['highlight']){
element.css("color",'red');
}else{
element.css("color",'green')
}
}
})
</script>
</head>
<body ng-app="my">
<div class="container">
<h2>今天是星期几?</h2>
<p ng-controller="ctr1" highlight="星期二">今天是{{ today }}</p>
<p ng-controller="ctr2" highlight="星期一">明天是{{ tommorrow }}</p>
</div>
</body>
</html>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325402025&siteId=291194637