JQuery. buildFragment source code analysis and role in constructing jQuery objects, jqueryfragment

Source: Internet
Author: User
Tags throw exception

JQuery. buildFragment source code analysis and role in constructing jQuery objects, jqueryfragment

This method appears in the back position of jQuery source code, mainly used in two places. 1 is used to construct a jQuery object. 2. It is used to provide underlying support for DOM operations, which is why we should first learn about it. I have analyzed jQuery constructor in the previous article and mentioned that there are 12 branches. One of them is handled by the jQuery. buildFragment method. What is the situation? When processing complex html tags, such as $ ('<div> 123 </div>'), you can use the ret variable inside the constructor to determine whether a simple tag is used, if this method is used, call the createElement method of js to directly create elements. If not, use this method to process the relevant explanations. For details, refer to the classification analysis of string conditions. This article mainly discusses the role of this method in constructing jQuery objects.

DocumentFragment

The documentFragment method in Javascript is used to create document fragments. What is a document fragment? The created element indicates a part of the document but does not belong to the document tree. It can be simply understood as a cached document element. We usually use it to create document elements, we can use the features of the document snippets to first create the document to be inserted in the document fragment and then insert it as a whole, which improves the performance compared to inserting document elements one by one. Here is an example:

 

// If You Want To create ten paragraphs, you may write the following code in the conventional method: var I = 0; I <10; I ++) {var p = document. createElement ("p"); var oTxt = document. createTextNode ("section" + I); p. appendChild (oTxt); document. body. appendChild (p);} Of course, this code is okay to run, but he called document ten times. body. appendChild () generates a page rendering every time. In this case, fragments are very useful: var oFragment = document. createDocumentFragment (); for (var I = 0; I <10; I ++) {var p = document. createElement ("p"); var oTxt = document. createTextNode ("section" + I); p. appendChild (oTxt); oFragment. appendChild (p); <br>} document. body. appendChild (oFragment );

 

In this Code, each new <p/> element is added to the document fragment, and the fragment is passed as a parameter to appendChild (). Here, the call to appendChild () does not actually append the File Fragment to the body element in this province, but only append the child nodes in the fragment. Then we can see the obvious performance improvement, document. body. appenChild () replaces 10 times at a time, which means only one Content Rendering and refreshing is required.
Implementation Principle

JQuery. the buildFragment method first creates a document segment and then calls jQuery. the clean method converts the result to a dom element. For better efficiency, jQuery adds a cache mechanism to this method, if it complies with the cache, a cache backup will also be provided for the next use when you read the settings from the cache.

Source code analysis
jQuery.buildFragment = function( args, nodes, scripts ) {    var fragment, cacheable, cacheresults, doc,

first = args[ 0 ];

...
}

First, it will accept the HTML code represented by the three parameters args to be converted to the DOM element. It is an array; nodes is also an array used to modify the document object used to create the document fragment; script stores script elements, which is mainly related to dom operations. In this case, I still think there is no concept where these parameters come from? Then look for the previously called method:

} else {          ret = jQuery.buildFragment( [ match[1] ], [ doc ] );          selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; }

When judging whether a tag is not a simple tag, the two items [match [1] and [doc] are passed in, now I know why the first two parameters are arrays. The first array is the matching tag. The second array is the document object. It may also be a jquery object or a dom element. Let's call it to see if the values of these parameters are greater. clear:

Create a jquery object in html

 <script>       $('<div><124/div>')   </script>

Then view the parameters in jQuery source code.

} else {   console.log(match[1]);    console.log(doc);    ret = jQuery.buildFragment( [ match[1] ], [ doc ] );    selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;}

Result of running in browser

<div><124/div>#document<!DOCTYPE html>

Another special one

  $('<div><124/div>',{'class':'test'});

Result of running in browser

<div><124/div>jquery-1.7.1.js:157 Object {class: "test"}

At this time, the doc is a common object. As for the third parameter, it is passed in the domManip method to operate the DOM first.

Then, five variables are declared. fragment points to the DocumentFragment file that may be created later. cacheable indicates whether the cache conditions are met. Only the files that meet the requirements can be cached; cacheresults is a file segment read from the cache object that contains the cached DOM element. The variable doc indicates the Document Object for creating the file segment; first is the first element of the array, because it is possible to create multiple elements, such as $ ('<div> 123 </div>, <a> 123 </a> '). Next let's look at the source code:

// nodes may contain either an explicit document object,    // a jQuery collection or context object.    // If nodes[0] contains a valid object to assign to doc    if ( nodes && nodes[0] ) {        doc = nodes[0].ownerDocument || nodes[0];    }

This code is used to process document objects. The passed nodes may be document objects, common objects, jQuery objects, or DOM elements.

If nodes exists and is not empty, first try to obtain its ownerDocument and assign it to the doc. To put it bluntly, it is the first situation to correct the DOM element.

    // Ensure that an attr object doesn't incorrectly stand in as a document object    // Chrome and Firefox seem to allow this to occur and will throw exception    // Fixes #8950    if ( !doc.createDocumentFragment ) {        doc = document;    }

Doc is used to modify the Document Object. Obviously, the previous method is not very good at processing only DOM elements, and this section is followed by processing not DOM elements, if the createDocumentFragment method does not exist, it means that the doc is equal to the document directly if it is not a DOM element. After the doc is corrected, it will always be the document Object of the document fragment.

    // Only cache "small" (1/2 KB) HTML strings that are associated with the main document    // Cloning options loses the selected state, so don't cache them    // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment    // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache    // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501    if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&        first.charAt(0) === "<" && !rnocache.test( first ) &&        (jQuery.support.checkClone || !rchecked.test( first )) &&        (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {        cacheable = true;        cacheresults = jQuery.fragments[ first ];        if ( cacheresults && cacheresults !== 1 ) {            fragment = cacheresults;        }    }

This section is for processing the cache. First, you must determine whether the cache conditions are met.

1. The length of the array args is 1, and the first element is a string, that is, the array args contains only a piece of HTML code.
2. The length of the HTML code is less than 512 (1/2 kb). Otherwise, the cache may occupy too much memory.
3. The Document Object doc is the current document object, that is, only the DOM elements created for the current document are cached, and other frameworks (iframe) are not cached.
4. HTML code starts with a left angle bracket, that is, only DOM elements are cached, and text nodes are not cached.
5. HTML code cannot contain the following tags: <script>, <object>, <embed>, <option>, and <style>.
6. The current browser can correctly copy the selected status checked of the single-choice button and check box, or the single-choice button and check button in HTML code are not selected.
7. The current browser can correctly copy HTML5 elements, or HTML code does not contain HTML5 tags.

The following four conditions use jquery's function detection and regular expression mainly to judge these conditions. Once these conditions are met, change the cacheable attribute to true to indicate that the cache conditions are met.

Then try. the fragments object reads the cache results. If you have created a dom element before. if the fragments object has results, you can directly call the cache result jQuery. the fragments method is in jQuery. after the buildFragment method is used, it is declared that the file segment used to save the cache is empty by default.

If cacheresults has a value and the value is not 1, the cache result is called and the result is assigned to fragment. Why is it regarded as 1? You can see it later.

jQuery.fragments = {};

Next let's look at the source code:

    if ( !fragment ) {        fragment = doc.createDocumentFragment();        jQuery.clean( args, doc, fragment, scripts );    }
If fragment has no value, it means that no results are cached, you can create a document fragment and hand it over to fragment. Then, you can call the clean method to convert it into a dom element. In fact, the clean method is used in the end. It is complicated to find a method and try again later.
    if ( cacheable ) {        jQuery.fragments[ first ] = cacheresults ? fragment : 1;    }    return { fragment: fragment, cacheable: cacheable };

Next, if the cache conditions are met, the results will be cached and saved to jQuery. in the fragments object, the result depends on whether cacheresults exists. If it does not exist, it means 1. This is why we need to judge cacheresults! = 1. Finally, an object containing a document fragment and whether the results meet the cache conditions are returned and processed based on the returned results.

Now let's take a full look at the usage of this method: First, if we pass in a complex tag for the first time to create a jQuery object, the document object will be corrected first to ensure that it is a document, then, the system checks whether the cache conditions are met and finds the jQuery object that stores cached file fragments. fragments: if there is a value, assign the result to cacheresults. If cacheresults has a value, assign it to fragment. because it is the first time it is used, it is definitely not worth f (! Fragment) is to call the js method fragment = doc. createDocumentFragment () at this time. Create the document fragment and use the clean method to process the document fragment to construct the jQuery object. Assume that the passed parameter supports caching, so the cacheable value is true but cacheresults does not exist, so the value of jQuery. fragments [first] is changed to one. When we use the same parameter for the second time, because it does not meet cacheresults! The condition = 1 will still be created by myself, but the cacheresults value is 1 at this time is not null. In this case, the created File fragment will be placed in jQuery. in fragments, jQuery is automatically called when the same parameter is used for the third time. fragments results, so the cache can be used for the third time. Why does jQuery need to call the cache for the third time? You can save the cache results in jQuery. fragments for the first time and call the results for the second time. It may be of other use that I haven't figured out yet. Complete source code is attached:

 1 Query.buildFragment = function( args, nodes, scripts ) { 2     var fragment, cacheable, cacheresults, doc, 3     first = args[ 0 ]; 4  5     // nodes may contain either an explicit document object, 6     // a jQuery collection or context object. 7     // If nodes[0] contains a valid object to assign to doc 8     if ( nodes && nodes[0] ) { 9         doc = nodes[0].ownerDocument || nodes[0];10     }11 12     // Ensure that an attr object doesn't incorrectly stand in as a document object13     // Chrome and Firefox seem to allow this to occur and will throw exception14     // Fixes #895015     if ( !doc.createDocumentFragment ) {16         doc = document;17     }18 19     // Only cache "small" (1/2 KB) HTML strings that are associated with the main document20     // Cloning options loses the selected state, so don't cache them21     // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment22     // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache23     // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #1050124     if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&25         first.charAt(0) === "<" && !rnocache.test( first ) &&26         (jQuery.support.checkClone || !rchecked.test( first )) &&27         (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {28 29         cacheable = true;30 31         cacheresults = jQuery.fragments[ first ];32         if ( cacheresults && cacheresults !== 1 ) {33             fragment = cacheresults;34         }35     }36 37     if ( !fragment ) {38         fragment = doc.createDocumentFragment();39         jQuery.clean( args, doc, fragment, scripts );40     }41 42     if ( cacheable ) {43         jQuery.fragments[ first ] = cacheresults ? fragment : 1;44     }45 46     return { fragment: fragment, cacheable: cacheable };47 };48 49 jQuery.fragments = {};

 


 

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.