Directive is the most important part of all AngularJS applications. Although AngularJS has provided a wide range of commands, it is often necessary to create application-specific directive (direves VES), which is the most important part of all AngularJS applications. Although AngularJS already provides a rich set of commands, you often need to create application-specific commands.
Speaking of AngularJS, we first came up with two-way data binding and command systems, which are also the most attractive part of AngularJS. There is nothing to say about two-way data binding, so today we will briefly discuss the Instruction System of the AngularJS framework. I am also a beginner and have read some materials, if there are some bad things, we hope to point out.
Commands are the most important part of AngularJS. Therefore, this framework also comes with a large number of commands. However, in development, these commands cannot meet our needs, therefore, we also need to customize some commands. Therefore, an AngularJS command can be expressed in HTML code in four forms:
1. Use it as a new HTML element.
Or
2. Used as an element attribute
3. Use as an element class
4. Use it as a comment
Note that there is a trap that requires a space after "directive: hello". Otherwise, there will be no effect. At the same time, we recommend that you use less comments, if you have to pursue a high level, you can just do it. Since commands have the above four forms of expression, how does one define them?
.directive('hello',function(){return {restrict:'AECM',template:'click me'}})
The above is the simplest Code to define a command, none of which. In the code above, the directive () method defines a new instruction. This method has two parameters. The first 'hello' indicates that the instruction name is hello, the second parameter is the function that returns the instruction object. In the code above, the function mainly uses two attributes to define the hello command:
1. The restrict [string] attribute is mainly used to specify the representation of instructions in HTML code. A Represents attributes, e Represents table elements, C Represents classes, and M represents annotations. In practice, we generally use the AE method.
2. The template [string or function] attribute specifies the HTML Tag generated after the instruction is compiled by Angular and linked. This attribute can be simply put in one HTML text, it can also be particularly complicated. When the value of this attribute is function, the method returns a string representing the template, and you can also use the {} expression in it.
template: function () {return 'click me';}
However, in general, the template attribute will be replaced by the templateUrl to point to an external file address. Therefore, we usually place the template in an external HTML file, then use templateUrl to point to him.
When defining commands, in addition to the above two basic attributes, we will also use many other attributes. Let's talk about them one by one:
1. priority [number] attribute, which specifies the priority of custom commands. When a DOM element has more than one command, you need to compare the priority of the command. The command with a higher priority must be executed first. This priority is used to sort the commands before executing the compile function. We will explain the compile function carefully below.
2. terminal [boolean] attribute. this parameter is used to determine whether to stop a command with a lower priority than this command on the current element. If the value is true, it is normal, the command is executed in the order of priority. If it is set to false, the command with a lower priority than the current command is not executed.
3. replace [boolean] attribute, which specifies whether the generated HTML content will replace the HTML element defining this directive. When we set the value of this attribute to true, open the console and you will find that the elements generated by this command will be like this:
When we set it to false, it will be like this:
.
4. link [function] attributes. In the above example, our custom commands do not make much sense. This is just the simplest command, there are many attributes that we didn't define for him, so they didn't have much purpose. For example, this link function includes three parameters: scope, element, and attrs. This link function is mainly used to add event listening to DOM elements, monitor model attribute changes, and update DOM. It contains three parameters:
1. scope parameter: when we do not define the scope attribute for the instruction, it represents the scope of the parent controller.
2. The element parameter is the DOM element encapsulated by the jQLite command (a subset of jQuery. If you have introduced jQuery before AngularJS, this element is a jQuery element, not a jQLite element. Since this element has been packaged by jQuery/jQLite, we don't need to use $ () For DOM operations.
Iii. attrs parameter, which contains the standardized parameter object of the attribute of the element where the instruction is located.
5. scope [boolean or object] attribute, which is used to define the scope of the instruction. The default value is false. That is to say, the instruction inherits the scope of the parent controller, you can use the attributes in the scope of the parent controller at will, but in this case, the attributes in the parent scope will be contaminated, which is not desirable. So we can let the scope take the following two values: true and {}.
If this parameter is set to true, Angular creates a scope inherited from the parent scope for the command.
var myapp=angular.module('myapp',[]).controller('myctrl',['$scope', function ($scope) {$scope.color='red';}]).directive('hello', function () {return{restrict:'AECM',replace:true,template:'click me',scope:true,link: function (scope,elements,attrs) {elements.bind('click', function () {elements.css('background-color','blue');})}}})
Here we define a color attribute for the parent scope and assign it to red. In the scope attribute of the hello instruction, we grant true, angular creates a scope that inherits from the parent scope for this instruction. Then, in the template attribute, we use the color attribute inherited from the parent scope, so the button will be red.
When it is {}, it indicates that an isolated scope is created and does not inherit the attributes of the parent scope. But sometimes we also need to access the attributes or methods in the parent scope. What should we do. Angular has long thought of this for us. There are three ways to remember the above operations:
I. Use @ to implement one-way binding. If we only provide this {} value for scope, the background color of the buttons in the code above will be gray ., If we need to use the color attribute of the parent scope, we can write as follows:
scope{color:'@color'}
Note: 1. the attribute color in scope represents the color in the expression {} of the template. The two must be consistent. 2. The value of the attribute color in scope, that is, the color after @, indicates the attribute color in the following HTML element. Therefore, the two must be consistent, if the attribute name here is the same as the name used in the expression {} in the template, You can omit the attribute name after @ and write it in the following format.
scope{color:'@'}
From the scope value in the instruction, we can see that the color in the expression {} in the instruction template points to the color attribute of the current element, the value of this color attribute is the value of the color attribute of the parent scope. The parent scope transmits the color attribute value to the color attribute of the current element, and then the color attribute passes the value to the color in the expression in the template. This process is unidirectional.
Ii. Use = to implement bidirectional binding
.directive('hello', function () {return{restrict:'AECM',replace:true,template:'click me',scope:{color:'='},link: function (scope,elements,attrs) {elements.bind('click', function () {elements.css('background-color','blue');scope.$apply(function () {scope.color='pink';})})}}})
Here, we bind the color attribute in the scope of the instruction to the color attribute in the parent scope in two ways, and add a click event to the link function of the instruction, click the button to change the color of the button, change the value of the color attribute of the instruction scope, add an input tag to the HTML page, and output or enter the value of the color attribute of the parent scope. Note that the {} expression does not need to be added to the attribute name value of the current element, because the parent scope transmits a real scope data model, instead of a simple string, we can transmit simple strings, arrays, and even complex objects to the scope of the instruction. Now let's see what will happen when we click this button.
Here we can see that the color of the button has changed to pink, indicating that clicking the button changes the color attribute of the scope of the instruction, resulting in a change in the color of the button. However, not only the buttons have changed, but the value in the input form has also changed to pink, which means that the color attribute of the parent scope has also changed. In addition, Let's enter a color in the input to see what has changed.
,
We can see that when we enter another color in the form, the color of the button also changes, which means that the color attribute of the scope of the instruction is changed. In summary, we can find that using '=' implements two-way binding.
3. Use & call methods in the parent scope
var myapp=angular.module('myapp',[]).controller('myctrl',['$scope', function ($scope) {$scope.color='red';$scope.sayhello= function () {alert('hello');};}]).directive('hello', function () {return{restrict:'AECM',replace:true,template:'click me',scope:{color:'=',sayhello:'&'},link: function (scope,elements,attrs) {elements.bind('click', function () {elements.css('background-color','blue');scope.$apply(function () {scope.color='pink';})})}}})
Here we also have two Points to Note: 1. We not only need to use the ng-click command in the template, but also bind the method in the parent scope to be called, in addition, you must add an attribute to the current element and direct it to the method of the parent scope to be called. 2. The attributes sayhello of the command scope, sayhello of the current element, and sayhello of the event Method bound to the template must be consistent. Then we can click the button to bring up a dialog box.
6. The transclude [boolean] attribute is used to determine whether the command can contain any content.
.directive('hello', function () {return{restrict:'AECM',replace:true,transclude:true,scope:{},template:'',}})
hello{{color}}
When its value is true, this is the value output on the page. When it is set to false, the page will be blank. Note that the color here is the color in the parent scope. It is not the color attribute of the scope in the instruction.
7. compile [function] parameter. This method has two parameters: element, attrs. The first parameter element indicates the element of the instruction, and the second parameter attrs indicates the Standardization List of the parameters granted to the element. Note that the compile function cannot access the scope and must return a link function. However, if the compile function is not set, you can configure the link function normally. (With compile, you cannot use link. The link function is returned by compile ).
.directive('hello', function () {return{restrict:'AECM',replace:true,translude:true,template:'click me',scope:{color:'=',sayhello:'&'},compile: function (element,attrs) {return function (scope,elements,attrs) {elements.bind('click', function () {elements.css('background-color','blue');scope.$apply(function () {scope.color='pink';})})};}}})
Now let's click this button.
We found that what happens after clicking the button is the same as the link attribute. In fact, there is no difference.
In most cases, we only need to use the link function. This is because most of the commands only need to consider registering event listening, monitoring models, and updating DOM, which can be completed in the link function. However, for commands such as ng-repeat, the DOM elements need to be cloned and repeated multiple times. The compile function is used to complete the tasks before the link function is executed. So why can't we use only one function to complete the generation process? To answer this question, we need to understand how commands are compiled in Angular!
8. How commands are compiled
When our angular application is started, angular will use the $ compile service to traverse DOM elements. After all the commands are identified, the compile method of the command will be called, return a link function and add it to the link function list that will be executed later. This process is called the compilation phase. Commands such as ng-repeat need to be repeatedly cloned many times. The compile function is executed only once during the compilation phase, and these templates are copied, however, the link function is executed for each copied instance. Therefore, separate processing improves the performance. (This sentence is not quite understandable. I copied it from other places. Http://blog.jobbole.com/62249/ here ).
9. The controller [string or function] and require [string or string [] parameters. When we want to allow other commands to interact with your commands, we need to use the controller function. When another command wants to interact, it needs to declare its reference to your command controller instance (require ).
.directive('hello', function () {return{scope:{},require:'^he',compile: function (element,attrs) {return function (scope,elements,attrs,cntIns) {cntIns.fn()};}}}).directive('he', function () {return {restrict:'AE',scope:{},controller: function ($scope, $compile, $http) {this.fn= function () {alert('hello');};}}})
After the page is loaded, a dialog box is displayed.
Well, the above is what I learned about angular and commands during this time. I will write it here first.