Preface
When we create an angularJS application, menus are often one of the indispensable elements. Perhaps when we are static menus, we will not find that there is no problem in operating the menu shrinking, collapse and expanding in the command, because before we operate, the page element rendering has been completed, so we can successfully find the target element through element in the command. However, once the data in our menu is not static but is loaded through the background interface to render dynamic data, we will find that after the instructions that were originally written statically cannot find the desired target element after being converted into dynamic data loading.
When I encountered such a problem, I started to feel weird. Of course, this is also a complaint. I still have to solve the problem well, and I have to check the pain, and be determined to clarify my thoughts and analyze the cause of the problem. First, let’s understand the life cycle of AngularJS.
The life cycle of AngularJS
Before the AngularJS application is started, they are saved in the text editor as HTML text. After the application is started, it will be compiled and linked, and the scope will be bound with HTML. The application can respond in real time to the actions performed by users in HTML. There are two main stages in the life cycle of AngularJS: one is the compilation stage and the other is the link stage.
AngularJS life cycle - compilation phase
During the compilation phase, AngularJS will traverse the entire HTML document and process the instructions declared on the page according to the directive definition in JavaScript. There may be another instruction in each instruction template, and another instruction may also have its own template. When AngularJS calls the instructions at the root of the HTML document, it will traverse all templates, and the template may contain instructions for the template. If an element already has a directive containing a template, never modify it with another directive, only the templates in the directive with the highest priority will be compiled.
Once the instruction and its sub-template are traversed or compiled, the compiled template will return a function called the template function. At this time, the DOM tree has not yet been data-bound, and there will only be little performance overhead for operating the DOM tree. Built-in instructions such as ng-repeat and ng-transclude will operate on DOMs that have not yet been data-bound at this time. For example, ng-repeat, it will traverse the specified array or object, build the corresponding DOM structure before data binding, and then pass the new DOM (compiled DOM) to the next stage in the instruction life cycle, linking the stage. Once the DOM of an instruction is compiled, it can be accessed immediately through the compile function. The signature of the compile function includes the element (tElements) where the access instruction declares it and the method of the element to other attributes (tAttrs).
compile returns an object or function. The compile() function is responsible for converting the template DOM, and the link() function is responsible for converting the scope and DOM.
//... compile: function(tEle,tAttrs,transcludeFn){ var tplEl = ('<div>' +'<h2></h2>'+'</div>'); var h2 = ('h2'); ('type',); ('ng-model',); ('hello'); (tplEl); return function(scope, ele, attrs){ //Connection function }; } //...
AngularJS life cycle - link stage
The link function creates instructions that can operate the DOM, and the link function is optional. The compiled function is defined and the link function returns. When both functions are defined, the compiled function will overload the link function.
//The relaxation of the following two definition instructions is exactly the same in function.('myApp',[]) .directive('myDirective', function (){ return { pre: function (tElement, tAttrs, transclude){ //Execute before the child element is linked, and after calling the 'link' function cannot locate the linked element }, post: function (scope, iElement, iAttrs, controllers){ //Execute after the child element is linked } } });
('myApp',[]) .directive('myDirective', function (){ return { link: function (scope, ele, attrs){ return { pre: function (tElement, tAttrs, transclude){ //Execute before the child element is linked, and after calling the 'link' function cannot locate the linked element }, post: function (scope, iElement, iAttrs, controllers){ //Execute after the child element is linked } } } } });
When a compiled function is defined to replace the link function, the link function allows us to provide the second method to return the object, that is, the postLink function. The link function will be called after the template is compiled and linked to the same scope.
//Link function signaturelink: function(scope, element, attrs){ //Operate DOM} //Includes require option, require someContainerlink: function(scope, element, attrs, someContainer){ //Operate the DOM here and you can access the controller specified by require.}
- scope-the scope used by the directive inside it;
- element--Article represents an instance element, which refers to the element that uses this directive;
- atrrs--represents instance attributes, is a standardized list of attributes defined on elements. They can be shared among link functions of all instructions and will be passed in the form of javascript objects;
- The controller parameter points to the controller defined by the require option. The require option is not set, and the controller's parameter is undefined;
The controller is shared among all instructions, so the instructions can treat the controller as a communication channel (public API). If multiple requirements are set, this parameter is an array of controller instances, rather than a separate controller.
Problem analysis
Through our understanding of the AngularJS life cycle, we can clearly understand why the dynamic menu binds the DOM operation on the linking stage did not succeed. Due to ng-repeat, I did not find the DOM element for the DOM tree operation. Because when encapsulating it into a menu instruction component, my internal menu data loading is implemented using ng-repeat, so only at this time can the operation on the DOM tree be bound inside ng-repeat.
Original writing:
//html <menu-bar> ````` <div ng-repeat="ml in menuLists"> `````` <div ng-repeat="mls in "> `````` <div ng-repeat="mlt in "> `````` </div> `````` </div> `````` </div> `````` </menu-bar> //directive ('',[]).directive('menuBar',function (){ return { restrict: 'E', replace: true, link: function (scope, element, attr){ //Logic code of the operation menu } } });
In this way, the code that operates the menu logic in the link is not triggered, and the detection mechanism of angularjs is useless. Because of ng-repeat, the DOM operation event is not mounted to the DOM, so it is impossible to successfully operate the menu. However, if the content of ng-repeat exists statically, the operations in the link function can be implemented.
Modified writing method:
//html <div ng-repeat="ml in menuLists"> `````` <div ng-repeat="mls in "> `````` <menu-bar> `````` <div ng-repeat="mlt in "> `````` <menu-bar> `````` </menu-bar> `````` </div> `````` </menu-bar> `````` </div> `````` </div> //directive ('',[]).directive('menuBar',function (){ return { restrict: 'E', replace: true, link: function (scope, element, attr){ //Logic code of the operation menu } } });
After modification, we put the instructions for operating the dynamically loaded DOM structure into ng-repeat. At this time, the logic is executed normally and the DOM structure can be printed in the link function.
The above is the AngularJS dynamic menu operation instructions introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support for my website!