Knockout source code Analysis of the implementation process

Source: Internet
Author: User

First, the implementation process

Second, the main class analysis

2.1. In applybindings, create the BindingContext and then execute the Applybindingstonodeanddescendantsinternal method
2.2. In the Applybindinstonodeanddescendantsinteranl method, the main completion of the current node binding, as well as the child node binding

functionapplybindingstonodeanddescendantsinternal (BindingContext, Nodeverified, Bindingcontextmaydifferfromdomparentelement) {varShouldbinddescendants =true; //Perf optimisation:apply bindings only if ...        //(1) We need to store the binding context on this node (because it could differ from the DOM parent node ' s binding conte XT)        //Note that we can ' t store binding contexts on non-elements (e.g., text nodes), as IE doesn ' t allow expando propert IES for those        //(2) It might bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)        varIselement = (Nodeverified.nodetype = = = 1); if(iselement)//workaround IE <= 8 HTML parsing weirdnessko.virtualElements.normaliseVirtualElementDomStructure (nodeverified); varShouldapplybindings = (iselement && bindingcontextmaydifferfromdomparentelement)//Case (1)|| ko.bindingprovider[' instance ' [' Nodehasbindings '] (nodeverified);//Case (2)        if(shouldapplybindings) shouldbinddescendants= Applybindingstonodeinternal (nodeverified,NULL, BindingContext, bindingcontextmaydifferfromdomparentelement) [' Shouldbinddescendants ']; if(Shouldbinddescendants &&!)Bindingdoesnotrecurseintoelementtypes[ko.utils.tagnamelower (nodeverified)]) {            //We ' re recursing automatically into (real or virtual) child nodes without changing binding contexts. So,            //* for children of a *real* element, the binding context was certainly the same as on their DOM. ParentNode,            //Hence bindingcontextsmaydifferfromdomparentelement is false            //* for children of a *virtual* element, we can ' t be sure. Evaluating. ParentNode on those children            //Skip over any number of intermediate virtual elements, any of which might define a custom binding context,            //Hence bindingcontextsmaydifferfromdomparentelement is trueApplybindingstodescendantsinternal (BindingContext, Nodeverified,/*bindingcontextsmaydifferfromdomparentelement:*/!iselement); }    }
2.3. Enter the Applybindingstonodeinternal method, which invokes the Bindingprovider Getbindingsaccessors method (for analyzing and retrieving bindings data, Main analysis Data-bind properties)
2.4. Create a Dependentobservable object (dependent on the Monitoring object)
varbindings; if(Sourcebindings &&typeofSourcebindings!== ' function ') {Bindings=sourcebindings; } Else {            varProvider = ko.bindingprovider[' instance '], getbindings= provider[' Getbindingaccessors ' | | Getbindingsandmakeaccessors;//Custom Bingindhandler            //Get The binding from the provider within a computed observable so we can update the bindings whenever            //The binding context is updated or if the binding provider accesses observables.            varBindingsupdater = ko.dependentobservable (//Dependent monitoring Objects                function() {//do a read, write processing, to achieve a two-way association (only read), the default is to perform a read. Bindings = sourcebindings?sourcebindings (BindingContext, node): Getbindings.call (provider, node, BindingContext); //Register A dependency The binding context to support observable view models.                    if(Bindings &&bindingcontext._subscribable) bindingcontext._subscribable (); returnbindings; },                NULL, {disposewhennodeisremoved:node}); if(!bindings | |!bindingsupdater.isactive ()) Bindingsupdater=NULL; }
2.5. Then analyze each binding in the bindings and create the INIT, Update method as a Dependentobservable object (where the execution of bindings is sequential).

Three, Bindingprovider analysis

This class mainly provides the parsing of Data-bind properties, mainly provides getbindings, getbindingsaccessors, parsebindingsstring (content use) method to assist the binding process. To create a function object:

functioncreatebindingsstringevaluator (bindingsstring, options) {//Build The source for a function, that evaluates "expression"        //for each scope variable, add a extra level of ' with ' nesting        //Example Result:with (SC1) {with (SC0) {return (expression)}}        varRewrittenbindings =ko.expressionRewriting.preProcessBindings (bindingsstring, Options), Functionbody= "with ($context) {with ($data | | {}) {return{"+ Rewrittenbindings +"}}} ";//Execute with Expression        return NewFunction ("$context", "$element", Functionbody); }
1, in the analysis of bindings, will distinguish NodeType 1, 8 of the type. If it is 8 (note), the Virtualnodebindingvalue method of the Virtualelements class is called to parse the binding result.

Four, bindings's sorting skill

See if the custom binding has an after property and recursively if it exists:

functiontopologicalsortbindings (bindings) {//Depth-first Sort        varresult = [],//The list of key/handler pairs that we'll returnbindingsconsidered = {},//A temporary record of which bindings is already in ' result 'Cyclicdependencystack = [];//keeps track of a depth-search so, if there ' s a cycle, we know which bindings caused itKo.utils.objectForEach (Bindings,functionpushbinding (bindingkey) {if(!Bindingsconsidered[bindingkey]) {                varbinding = ko[' Getbindinghandler '] (Bindingkey); if(binding) {//First add dependencies (if any) of the current binding                    if(binding[' after ') {//dependency detection, adding an after reference to the array before adding the current itemCyclicdependencystack.push (Bindingkey); Ko.utils.arrayForEach (binding[' After ',function(bindingdependencykey) {if(Bindings[bindingdependencykey]) {if(Ko.utils.arrayIndexOf (Cyclicdependencystack, Bindingdependencykey)!==-1) {                                    ThrowError ("Cannot combine the following bindings, because they has a cyclic dependency:" + cyclicdependencystack.join (",")); } Else{pushbinding (Bindingdependencykey);                        }                            }                        }); Cyclicdependencystack.length--; }                    //Next Add the current bindingResult.push ({key:bindingkey, handler:binding}); } Bindingsconsidered[bindingkey]=true; }        });

Five, attention

1. All Dependentobservable objects, the Readfunction method is executed one time by default during the creation process.

Knockout source code Analysis of the implementation process

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.