Deep analysis of the backbone.js framework of the role of dependent library underscore.js _ basic knowledge

Source: Internet
Author: User
Tags extend html tags hosting

Backbone must rely on underscore.js to be able to use it, it must complete the basic operation of accessing page elements and processing elements through functions in underscore.
Note: Backbone can work well with other JS libraries, so that it is a library, not a framework.
Underscore does not extend the native object, but calls the _ () method for encapsulation, once the encapsulation is complete, the JS object becomes underscore object, or the data in the native JS object can be obtained by the underscore object's value () method. (jquery gets the jquery object through the $ () method)
Underscore has a total of more than 60 functions, according to the different processing objects, can be divided into collection class, array class, function class, object class, Tool function class five types of modules.

Underscore template () function Description:

The function contains three types of templates:

(1) <%%>: Contains logical code, rendering will not be displayed.
(2) <%=%>: Data type, display data after rendering.
(3) <%-%>: Converts HTML tags into common strings to avoid code attacks.

Call Format:

_.template (templatestring, [data], [setting])

No two-way data binding is implemented.

1, underscore object encapsulation
underscore does not extend in native JavaScript object prototypes, but, like jquery, encapsulates data in a custom object (hereinafter referred to as "underscore object").
You can get native JavaScript data by calling a underscore object's value () method, such as:

Defines a JavaScript built-in object 
var jsdata = { 
 name: ' Data '}/// 
 
The object is created as a underscore object by the _ () method 
The Underscoredata object's prototype contains all the methods defined in underscore, and you can use 
var underscoredata = _ (jsdata) arbitrarily; 
 
The primary data is obtained by the value method, i.e. Jsdata 
underscoredata.value ();

2, priority invoke JavaScript 1.6 built-in method
There are many methods in the underscore that have been incorporated into the specification in JavaScript1.6, so the built-in methods provided by the hosting environment (if the hosting environment has implemented these methods) are given precedence within the underscore object to improve the execution efficiency of the function.
For hosting environments that do not support JavaScript 1.6, underscore is implemented in its own way, which is completely transparent to developers.
The hosting environment here is probably the Node.js runtime environment, or the client browser.

3. Change the name space
underscore uses _ (underscores) to access and create objects by default, but that name may not conform to our naming conventions or can easily cause naming conflicts.
We can use the Noconflict () method to change the name of the underscore and restore the value before the _ (underlined) variable, for example:

<script type= "Text/javascript" > 
 var _ = ' custom variable '; 
</script> 
<script type= "Text/javascript" src= "Underscore/underscore-min.js" ></script> 
<script type= "Text/javascript" > 
 //Underscore Object 
 Console.dir (_); 
 Rename the underscore object to us, followed by us to access and create the underscore object 
 var us = _.noconflict (); 
 Output "Custom variable" 
 Console.dir (_); 
</script> 

4, chain-type operation
Remember how we did the link operation in jquery? For example:

$ (' a ') 
 . css (' position ', ' relative '). 
 attr (' href ', ' # ') 
 . Show (); 

Underscore also supports chained operations, but you need to first invoke the chain () method to declare:

var arr = [A, m]; 
_ (arr) 
 . Chain (). 
 Map (function (item) {return item++;}) 
 . A () 
 . Value (); 

If the chain () method is invoked, underscore encapsulates the called method inside a closure and encapsulates the return value as a underscore object and returns:

This is the key function in underscore to implement a chained operation that encapsulates the return value into a new underscore object and calls the chain () method again to support the next function in the method chain. 
var result = function (obj, chain) {return 
 chain? _ (obj). Chain (): obj; 
} 

5. Extended Underscore
we can easily extend the custom method to underscore by Mixin () method, for example:

_.mixin ({ 
 Method1:function (object) { 
 //Todo 
 }, 
 method2:function (arr) {/ 
 /Todo 
 }, 
 method3:function (FN) { 
 //Todo 
 } 
}); 

These methods are appended to the underscore prototype object, and all created underscore objects can use these methods, and they enjoy the same environment as other methods.

6, traverse the collection
the each () and map () methods are the most commonly used two methods used to iterate over a collection (an array or an object) and to sequentially process each element in the collection, for example:

var arr = [1, 2, 3]; 
 
_ (ARR). Map (function (item, i) { 
 Arr[i] = Item + 1; 
}); 
 
var obj = { 
 first:1, 
 second:2 
} 
 
_ (obj). each (function (value, key) {return 
 Obj[key] = value + 1; 
}); 

The map () method has the same function and parameters as the each () method, but it records the results returned by each iteration function to a new array and returns.

7. Function throttling
function throttling is the control of the execution frequency or spacing of a function (like the gate that controls the flow), underscore provides debounce () and throttle () Two methods for function throttling.
To describe these two methods more clearly, suppose we need to implement two requirements:

Requirement 1: When the user enters the search condition in the text box, automatically queries the matching keyword and prompts the user (as in Tmall input search keyword)
First analysis of the 1th requirement, we can bind the text box KeyPress event, when the input box content changes, query matching keyword and display. Suppose I wanted to query "Windows Phone," which contains 13 characters, and I entered it for only 1 seconds (as if it were a bit fast, meaning it), and then within 1 seconds, I called the 13 query method. This is a very scary thing, and if Tmall, I fear it will hang up before the Singles Day (of course, it's not that fragile, but it's definitely not the best solution).
Better yet, we want the user to have entered the completion, or are waiting for the prompt (perhaps he is too lazy to enter the later content), and then query the matching keyword.
Finally, we found that in both cases we expect the user to temporarily stop typing, so we decide to query after the user pauses typing for 200 milliseconds (if the user is constantly typing, we think he may be very clear about the keyword he wants, so wait a second before prompting him)
At this point, using the Debounce () function in underscore, we can easily implement this requirement:

<input type= "text" id= "search" name= "search"/> <script type= 
"Text/javascript" > 
 var query = _ ( function () { 
 //query operations here 
 }). debounce; 
 
 $ (' #search '). Bind (' keypress ', query); 
</script> 

As you can see, our code is very concise, throttling control has been implemented in the Debounce () method, we only tell it that when the query function is not invoked within 200 milliseconds, execute our query operation, and then bind the query function to the KeyPress event of the input box.
How does the query function come from? When we call the Debounce () method, we pass a function that executes the query and a time (in milliseconds), and the Debounce () method throttles the function based on the time we pass, and returns a new function (the query function). We can confidently invoke the query function, and the Debounce () method will help us to control it as required.

Requirement 2: When the user drags the browser scroll bar, the calling server interface checks for new content
To analyze the 2nd requirement, we can bind the query method to the Window.onscroll event, but this is obviously not a good idea, because dragging a scroll bar once may trigger dozens of or even hundreds of onscroll events.
Can we use the Debounce () method above for throttling control? When the user drags the scroll bar, then query for new content? However, this is inconsistent with the requirements, and users want to see changes in the new content as they drag.
So we decided to do this: when the user drags, the interval of every two queries is not less than 500 milliseconds, and if the user drags for 1 seconds, this may trigger 200 onscroll events, but we only do 2 queries at a time.
Using the throttle () method in underscore, we can also easily implement this requirement:

<script type= "Text/javascript" > 
 var query = _ (function () { 
 //query operations here 
 }). Throttle; 
 
 $ (window). bind (' scroll ', query); 
</script> 

The code is still very concise, because within the throttle () method, all the controls that have been implemented for us.

You may have found that the debounce () and throttle () Two methods are very similar (including invocation and return values) and have different effects.
They are all for function throttling, and control functions are not frequently invoked to save client and server resources. The
 debounce () method focuses on the interval at which functions are performed, that is, the call time of the function two times cannot be less than the specified time. The
Throttle () method is more concerned with the execution frequency of functions, that is, functions are only invoked once in a specified frequency. The
 8, template resolution
underscore provides a lightweight template-resolution function that helps us effectively organize page structures and logic.
I'll introduce it through an example:

<!--to display the rendered tag--> <ul id= "element" ></ul> <!--define the template, placing the template content in a script label--> <script type= "Text/template" id= "TPL" > <% for (var i = 0; i < list.length; i++) {%> <% var item = list[i]%> &l t;li> <span><%=item.firstName%> <%=item.lastName%></span> <span><%-item.city% ></span> </li> <%}%> </script> <script type= "Text/javascript src=" underscore/unders Core-min.js "></script> <script type=" Text/javascript >//Get render element and template content var element = $ (' #element '), t 
 
 PL = $ (' #tpl '). html (); Create data, which may be the Var data you get from the server = {list: [{firstName: ' <a href= ' # ' >Zhang</a> ', lastName: ' San ', CIT Y: ' Shanghai '}, {firstName: ' Li ', lastName: ' Si ', City: ' <a href= ' # ' >Beijing</a> '}, {firstName: ' Wang ', LastName: ' Wu ', City: ' Guangzhou '}, {firstName: ' Zhao ', lastName: ' Liu ', City: ' Shenzhen '}]}//parse template, return parsed innerRong var html = _.template (TPL, data); 
Fills the parsed content to the render element element.html (HTML); 
 </script>

In this case, we put the template content in a <script> tag, and you may have noticed that the type of the label is text/template rather than text/javascript because it cannot be run directly as a JavaScript script.
I also recommend that you put the template content in <script>, because if you write them in a <div> or other tag, they may be added to the DOM tree for parsing (even if you hide the tag, you can't avoid it).

The _.template template function can parse only 3 template tags (this is much simpler than smarty, JSTL):
<%%>: Used to contain JavaScript code that will be executed when the data is rendered.
<%=%>: For outputting data, it can be a variable, a property of an object, or a function call (will output the return value of a function).
<%-%>: Used to output data while converting the HTML characters contained in the data into an entity form (for example, it converts double quotes to "form") to avoid XSS attacks.
<%-%> tags are often used when we want to display HTML as text in the data.
Underscore also allows you to modify the form of these 3 tags, if we want to use {%%}, {%=%}, {%-%} as a label, you can modify the templatesettings to achieve, like this:

_.templatesettings = { 
 Evaluate:/\{% ([\s\s]+?) \%\}/g, 
 interpolate:/\{%= ([\s\s]+?) \%\}/g, 
 escape:/\{%-([\s\s]+?)%\} /g 
} 

In this case, we pass the template content and the data that needs to be populated to the template method, which is processed in the following order:

(1) Parsing the template content into executable JavaScript (parsing template label)
(2) The parsed JavaScript scope is modified by the WITH statement to the data object we pass, which enables us to access the properties of the data object directly in the template through the variable form
(3) Perform parsed JavaScript (populate the template with data)
(4) Return the results after execution
We often encounter a situation in which the template method is called multiple times to render the data to the same template.
Suppose we have a paging list where every piece of data in the list is rendered by the template, and when the user goes to the next page we get the next page of data and render it, which is actually the same one every time the template is rendered, but all the processing of the template just described will always be performed.
In fact, underscore's template method provides a more efficient way to invoke, and we modify the last two sentences in the code above to read:

Parse template, return parsed content 
var render = _.template (TPL); 
var html = render (data); 
Fills the parsed content to the render element 
element.html (HTML); 

You'll find subtle differences: When we call the template method, we only pass the template content, not the data, at which point the template method parses the template content, generates the parsed executable JavaScript code, and returns a function, The function body is the parsed JavaScript, so when we call the function to render the data, it eliminates the action of the template parsing.

You should store the returned function (as I store it in the render variable), by calling the function to render the data, especially if the same template is likely to be rendered multiple times, this can improve execution efficiency (how much you want to increase depending on the length and complexity of your template). But anyway, it's a good habit).

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.