ANGULARJS Directive Comprehensive interpretation (1.4.5)

Source: Internet
Author: User

Speaking of ANGULARJS directive that is the directive, so to speak angularjs the soul is the instruction, learn ANGULARJS command then your ANGULARJS martial arts to cultivate half, of course, this is only a little bit of original opinion, nonsense not much said, The following is the use of ANGULARJS instructions and source code implementation interpretation.

Learn angularjs directive then we'll take 3 questions to learn:

1. What is the angular directive?
2. How does the instruction define the stored?
3. How does the instruction compile and run?

1. First, the 1th interpretation of what is the directive:

At a, directives is markers on a DOM element (such as an attribute, element name, comment or CSS class) that T Ell AngularJS ' s HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM Elem ENT and its children. (This is what the official website says)

Directives are custom tags attached to HTML elements (for example, attributes, elements, or CSS classes) that tell Angularjs's HTML compiler ($compile) to append some specified behavior to an element, even manipulate the DOM, alter the DOM element, and its sub-nodes at all levels. (This is my personal opinion defined by the interpretation of the official website)

It can be seen that the instructions are custom HTML tags used to solve the repeated crud (create read change delete) operation to modify the DOM, where small partners want to learn ANGULARJS operation DOM, then the small partners first need to understand D1, D2, And what the D3 achieved and what the structure was optimized for. Again to learn Angularjs will be a step forward!

Okay, 1th, we know the concept. So let's see how to use the ANGULARJS directive:

instruction Example:

<div ng-controller= "Controller" >
Hello <input ng-model= ' name ' > <span self-app></span> <br/>
<span self:app></span> <br/>
<span self_app></span> <br/>
<span data-self-app></span> <br/>
<span x-self-app></span> <br/>
</div>

It can be seen here that if the instruction is registered as attribute (attribute) Then there are 5 legal calls in the method:

The first is called by _ to refer to the

The second type: to invoke the command

The third way to invoke commands

The fourth one invokes the instruction in data-xxx-xxx.

The fifth one invokes the instruction in x-xxx-xxx.

2. The 2nd Interpretation instructions How to define the stored :

Directive through

Angular.module (' Selfapp ', [])
. directive (' mydirective ', function () {
Returns an object (called a directive object for the moment)
return {
Restrict: ' A ',//e a M C
Replace:true,
Scope:true,
Template: ' <span>hello world</span> ',
Compile:function (telement) {
Console.log (' Complile: ', telement);
return function (scope, elem) {
Console.log (' 1 ');
}

}

}

});

Here we can see that through our pre-registered module to the first one of the instructions, if we want to understand how the instructions are stored then we should look at the source code,

Directive:invokelaterandsetmodulename (' $compileProvider ', ' directive ')//angular.js 2172 lines

This is the internal method of the Angularjs module,

Delay call and Set module name

function Invokelaterandsetmodulename (provider, method) {
return function (Recipename, factoryfunction) {

Name the module variable for the factory function
if (factoryfunction && isfunction (factoryfunction)) factoryfunction.$ $moduleName = name;

Store our registered instructions in the call queue
Invokequeue.push ([Provider, method, arguments]);

Return to our module instance
return moduleinstance;
};
}

Here we can know that in fact we register a command to actually just store our instructions in the call queue to wait for the call.

3. How does the 3rd interpretation instruction compile and run?

In fact, when the call is compiled ANGULARJS directive time is angularjs own compilation mechanism, will use $compileprovider directive method to compile instructions, Compileprovider method is as follows:

It's actually here. $compileprovide Register as a service to invoke

$CompileProvider. $inject = [' $provide ', ' $ $sanitizeUriProvider '];//angular.js 6919 lines
function $CompileProvider ($provide, $ $sanitizeUriProvider) {

Okay, here comes the play.

Instruction storage container, one instruction can have multiple directive factory functions (i.e. multiple instruction objects)

this.directive = function registerdirective (name, directivefactory) {


Assertnothasownproperty (name, ' directive ');

There's no point here. Verify that the directive name is a string type
if (isstring (name)) {

Or is the test order name legal?
Assertvaliddirectivename (name);

Construct a command factory
Assertarg (directivefactory, ' directivefactory ');

Check if the directive has an instruction factory, if not, continue.
if (!hasdirectives.hasownproperty (name)) {
Hasdirectives[name] = [];

$provide. Factory (name + Suffix, [' $injector ', ' $exceptionHandler ',
function ($injector, $exceptionHandler) {

Define a command factory collection
var directives = [];

Loops through the Command factory collection and collects the instruction objects returned by each factory function
ForEach (Hasdirectives[name], function (directivefactory, index) {
try {

Call the factory function, this is $injector, so the factory function can also be a function or an array with dependency injection.
var directive = $injector. Invoke (Directivefactory);

Check if the instruction is a function and the instruction we defined earlier is actually a function
if (isfunction (directive)) {
directive = {compile:valuefn (directive)};

If the compile function is present in the directive, the link function is not run
} else if (!directive.compile && directive.link) {
Directive.compile = Valuefn (Directive.link);
}
directive.priority = Directive.priority | | 0;
Directive.index = index;
Directive.name = Directive.name | | Name
Directive.require = Directive.require | | (Directive.controller && directive.name);
directive.restrict = Directive.restrict | | ' EA ';
var bindings = directive.$ $bindings =
Parsedirectivebindings (Directive, directive.name);
if (IsObject (Bindings.isolatescope)) {
directive.$ $isolateBindings = Bindings.isolatescope;
}
directive.$ $moduleName = directivefactory.$ $moduleName;
Directives.push (Directive);
} catch (e) {
$exceptionHandler (e);
}
});
return directives;
}]);
}

Store current Command Factory
Hasdirectives[name].push (directivefactory);
} else {
ForEach (name, Reverseparams (registerdirective));
}

Finally, a chained call is provided
return this;
};

Okay, all right. The source code interpretation is complete, we are not the instructions have a system concept, but also know how ANGULARJS directive is running down, then summed up:

1. When registering a directive, a factory function (which supports dependency injection) is registered, and it is responsible for returning the instruction object
2. One instruction can register multiple factory functions, which means that there will be multiple instruction objects (that is, the set of instruction objects), in fact, there are some conflicts between multiple instruction objects, such as having only one template, having an isolated scope, etc.
3. A set of instruction objects corresponding to an instruction is acquired by the outside world by registering as a service.

OK, the following describes the interpretation of the internal parameters when defining an instruction: (as a professional IT worker, the show will do the full set!) )

Name-the names of the current scope, which can be used at the time of registration (not required).

Priority-(precedence)-when multiple directive are defined on the same DOM element, it is sometimes necessary to clarify their order of execution. This property is used to sort before the directive compile function call. If the precedence is the same, then the order of execution is indeterminate (initially, high priority is performed first, and at the same time, it is performed at the same level as the stack-like "post-binding".) In addition, the test is a bit careless, when defining directive, two times defined a directive of the same name, but the execution results found that two compile or link function will be executed).

Terminal -(last group worked)

             -If set to true, indicates that the current priority will be the last set of Directive executed. Any directive is the same as the current priority, they will still execute, but the order is indeterminate (although the order is indeterminate, but basically              ,     In accordance with the order of priority. The lower priority will no longer execute after the current priority is executed.

Scope  - true-A new scope will be created for this directive. If there is more than one directive in the same element that requires a new scope, it will only create a scope. The new scope rule does not apply to the root template (root of the                           TEMP Late), so the root template often gets a new scope. This scope is a new, independent (isolate) scope. The difference between the "isolate" scope and the general scope is that it is not inherited from the parent scope by the prototype. This is helpful in                 To create reusable components that can effectively prevent reading or modifying the data of the parent scope. This standalone scope creates a local scope property that has a set of parent scopes from the                 and nbsp   Object Hash. These local properties are useful for creating aliases of values for templates (useful for aliasing values for templates!). A local definition is a hash mapping of a set of local scope property to its source (Locals                  definition is a Hash of local scope property to its source)) ():

                   @ or @attr-establishes a local scope property-to-dom binding. Because the property value is always a string type, this value always returns a string. If the property name is not specified by @attr, then the local name will be associated with                           &NBS P              dom The name of the property has been. For example <widget my-attr= ' Hello {{name}} ' >,widget's scope definition is: {localname: ' @myAttr '}. Then, the Widget scope property's localname will be mapped                                                 out "Hello {{name}}" True value after conversion. When the Name property value is changed, the LocalName property of the widget scope also changes accordingly (only one-way, different from the following "="). The Name property is read in parent scope                                         (not component scope)

                    = or =expression (this may be attr)-the local scope property and the Paren T set the two-way binding between the scope property. If you do not specify a attr name, the local name will be the same as the property name. For example <widget my-                                                  attr= "Parentmodel" >,widget defined scope is: {Localmodel : ' =myattr ', then the Widget scope property "LocalName" will map the "Parentmodel" of the parent scope. If Parentmodel occurs                              / nbsp       Any changes, Localmodel will also change, and vice versa. (bidirectional binding)

                   & or &attr-Provides a way to execute an expression in the context of the parent scope. If you do not specify a name for the attr, the local name will be the same as the property name. For example <widget my-attr= "Count = Count + value",                     &N Bsp                       widget is defined as: {localfn: ' Increment () '}, then is Olate the Scope property "LOCALFN" points to a function that wraps around the increment () expression. In general, we want to use an expression                               & nbsp         type, transfer data from isolate scope to parent scope. This can be done by transferring a local variable key value mapping to the wrapper function of the expression. For example, if the expression is increment (amount), then                           &N Bsp         We can call LOCALFN by LOCALFN ({amount:22}) to specify the value of amount.

Controller -controller constructor. The controller initializes before the Pre-linking step and allows the other directive to be shared by the require of the specified name (see the Require property below). This will allow directive to communicate with each other and enhance the behavior between them. The controller injects the following local objects to link by default:

$scope-scope that is combined with the current element
$element-The current element
$attrs-Property object for the current element
$transclude-A transpose linking Function:function (CLONELINKINGFN) that is pre-bound to the current transpose scope. (A transclude;linking function pre-bound to the correct transclusion scope)

require -Request another controller to pass in the linking function of the current directive. Require need to pass in the name of a directive controller. If the controller is not found for this name, an error will be thrown. The name can include the following prefixes:

? -Do not throw an exception. This makes this dependency an optional option. <br/>
^-Allows you to find the parent element's controller<br/><br/>

Restrict -eacm a subset of the string, which restricts directive to the specified declarative way. If omitted, directive will only allow through attribute declarations: E-element name A-property name C-class M-Comment

Template -If replace is true, replaces the template content with the current HTML element and migrates the original element's attributes, class, or false to treat the template element as a child of the current element.

Templateurl -The template is basically consistent, but the template is loaded with the specified URL. Because the template loading is asynchronous, compilation, linking are paused, waiting for the load to be completed before executing.

Replace -if set to True, the template replaces the current element instead of being added to the current element as a child element. (Note: When True, the template must have a root node)

transclude -compiles the contents of the element so that it can be used by the directive. You need to use (reference) with Ngtransclude (in the template). The advantage of transclusion is that linking function can obtain a transclusion function that is pre-bound to the current scope. In general, create a widget that creates a isolate scope,transclusion not a child, but rather a sibling of isolate scope. This will allow the widget to have a private state, and the transclusion will be bound to the parent (preisolate) scope.

True-Converts the contents of this directive.

' Element '-converts the entire element, including other lower-priority directive. (as if the whole content is compiled, as a whole (outside the package p), inserted into the specified place)

compile -compile function

link function, which is used only if the Compile property is not defined.

Well, the above content is my humble opinion, hope that we can better understand the use and principle of ANGULARJS directive. Reprint please specify the source! Thank you

ANGULARJS Directive Comprehensive interpretation (1.4.5)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.