Angular 1.0 source code analysis

This article analyzes the source code process of angular 1.0 from initialization to compiling webpage update pages and some important details.

Example of test project:

<html ng-app='myapp' >
<body ng-controller="myController" >
<tip title="title"></tip>
</body>

Controllers and directives are defined using the methods of angular.module.
Angular 1.0 is centered on the directive, the directive directive label is the component, there is a template, and the attribute directive is mainly to modify the attribute of the element, angular 2.0 is changed to a component-centered design.


Angular entry initializer:
function angularInit(element, bootstrap) {
  bootstrap(appElement, module ? [module] : []);
}

function bootstrap(element, modules) {

  var doBootstrap = function() {

// Compile the root element, return the link function, and then execute the link function. The code to update the page is in the update method of each instruction expression watcher.       });











    }]);
  return injector;
  };
  return doBootstrap();

}

function createInternalInjector(cache, factory) {
  function invoke(fn, self, locals){ //invoke is to transform parameters and scope to call the function, the angular internal object mechanism and dependency module injection are very complicated, this article ignores
    fn = fn[length] ;
    return fn.apply(self, args);

 


function compile($compileNodes, transcludeFn, maxPrior // compile from root element
  var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, // recursively compile child nodes
    function compileNodes(nodeList, transcludeFn, $rootElement,

      applyDirectivesToNode(directives,

        function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
          $compileNode.html(directiveValue); // Insert the directive's template<div>{{title}}</div> into the node element in the web page

      childLinkFn = compileNodes(childNodes,nodeLinkFn ? nodeLinkFn.transclude : transcludeFn); // If there is a child node, call itself recursively
      return linkFnFound ? compositeLinkFn : null;
// Every time the child node is recursed, the instruction of the child node has been compiled, recursive child node When returning to the top-level compile code position layer by layer, the returned link function already contains
the link function generated during each layer of recursion, that is, the compilation result of each layer of recursion. Finally, as long as the final returned link function is executed, the root scope is passed, and the root scope is saved
in the root element object attribute, the entire process of compiling and inserting the webpage is completed. If there is an instruction to compile the child node recursively, the instruction will be compiled.

If it is a routing component, there is a template, which is compiled and inserted into the webpage to take effect.

function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) { //The link function returned by each recursion, including the result data of each recursive compilation
  return function publicLinkFn(scope, cloneConnectFn, //The link function returned by compile, will be returned after return Execute the link function to pass the scope
    $linkNode.eq(i).data('$scope', scope); // node is the element jquery object, save the scope to the attribute of the element object
      if (cloneConnectFn) cloneConnectFn($linkNode, scope );
      if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode); // The link function contains layers of recursive compilation result data
      return $linkNode;

Angular's link function is rather confusing. It is mainly related to elements and scope/controller instance. Generally, it is useless. The scope starts from the rootscope as a tree structure. From the rootscope, all child scopes can be recursed.

The controller method refers to a scope that has already been created. The scope is distinguished and indexed by id, which has nothing to do with the element. The data level has no direct relationship with the element.

Compile method compile coat $apply, $apply will call $digest:
  $digest: function() {
    //Recursive scope to find watcher, there is no scope in the watcher data, so the scope should be passed when executing the watcher method, and the watcher method will be executed when the watcher method is executed. The transformation scope is scope
    value = watch.get(current) // When getting the value of the expression, you need to pass the scope, the value of the expression {{title}} is hello
    watch.fn(value, ((last === initWatchVal) ? value : last), current); // After executing watch.fn, the web page displays hello, fn is the handler/update function

The code also involves defer and settimeout as delay functions that implement asynchronous scheduling and non-functional processes.


Therefore, Angular builds a watcher for each expression when compiling the web page at initialization. The compiler coats $apply and calls $digest to scan and execute the watcher's update method to update the web page.


Vue also establishes a watcher for each expression when initializing and compiling the template, and establishes a set/get method for the data attribute of the component. As long as the set data operation is performed, the update update page of the corresponding watcher will be executed.
Vue 2.0 builds a watcher for components. When initializing, the root component is compiled to execute the update update page of the root component watcher. When the data is set, the update method of the watcher of the corresponding component is executed to update the page. The component
may have sub-components nested, then recursively reload from the component. Compile the template to generate vnode, and then update the page according to vnode.

Angular is to perform $digest scan to perform watcher update page after data operation, vue is to set trigger to perform watcher update page.

React is to recursively compile child nodes when initializing and compiling, and then insert the compilation results into the web page to take effect. When the data changes, execute the component's render() method through the Connect component's Listener or setState to recompile the component's
update page.

Both angular and vue use the compile method to recursively compile web page elements. This is their core program. React is also similar. Its mountComponent is actually a recursive compiler program. Therefore, all frameworks actually use similar design methods in terms of basic principles and methods. , both design a core compiler that recursively compiles all child nodes.

The way of writing templates and expressions is different. React is special. It uses the render() method to write templates, uses JSX syntax, and uses babel to compile and parse, and generate a function with layers of nested createElement() to execute this The function produces a root element.

Vue 2.0 also uses a similar method, compiling the template to generate a render method code, including layers of nested createElement methods, and then executing the render method code to generate a root element Element.

 

Guess you like

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