The first two briefly discussed the architecture of Requirejs+angular and Requirejs+backbone, both of which are estimated to be the most popular practices in the country.
Talking about HTML5 single page architecture (i)--requirejs + angular + angular-route
On HTML5 single page Architecture (ii)--backbone + Requirejs + zepto + underscore
However, this article, I would like to further explore the advantages and disadvantages of these two frameworks, in addition, further, put aside these two frameworks, back to the real, and make a simple route to achieve a single page.
This for just do the front-end development of the new classmate is the best, if one came to the post on a lot of angular, backbone, requirejs, look at the information for a two weeks. In fact, we are most familiar with the dollar $, the dollar can solve the problem, do not trouble to angular, backbone big uncle.
In advance, due to my narrow business scope, not necessarily can be angular and backbone functions are used again, so the following analysis may be biased, welcome to discuss.
Angular Advantages:
- Powerful data two-way binding
- Component of the View interface layer
- Built-in powerful services (such as form validation)
- Simple routing
Angular Disadvantages:
- The introduction of JS larger, for the mobile side is a little too much
- Complex grammar, high learning costs
Backbone Advantages:
- The introduction of JS smaller
- Clear MVC Layering
- Model Layer Event mechanism
- Simple Routing and easy extension
Backbone Missing points:
- MVC is a bit rigid, sometimes it feels cumbersome.
- No two-way binding, interface modification can only rely on their own
- When the view switch, there is not enough convenient event notification (to listen to the route yourself)
In fact, these two frameworks are very good, but in the actual business, not necessarily hundred test lark, because there are some mobile single page web, the business is very simple, but the route to switch to a few sub-modules, each sub-module basically pull the data, show to the user, very few user interaction to modify the data, Change the functionality of the view.
For this situation, the use of angular is a bit overkill feeling, and backbone although a lot of small, but the function of the model is also wasteful.
So, here, I would like to discuss whether we can put aside these two frameworks and just ask for our basic needs and build a simpler framework.
Experience, some class libraries are essential:
- Requirejs: module Partitioning
- Zepto: Mobile-side jquery
- Underscore: easy-to-base approach, including template templates, each, map, and more
- Lu Yucu: Here first uses director.js, however this thing does not have backbone and angular the route to be useful, the article finally discusses this question
Make the simplest structure of your own, the idea is very simple:
- Start the program
- Listen for routing
- Routing changes, mapping to the corresponding processing logic, loading the corresponding modules
- Module loading complete, modify DOM, i.e. view
- When the page jumps, remove the previous module and load the next module, that is, back to the 3rd
Simple ideas, so that the architecture is very concise and clear, new team members come to be able to easily get started, and angular and backbone architecture, less than 2, 3 days to fit into an existing project.
Next, let's look specifically at how to do it.
The first step, or the index.html
<!DOCTYPE HTML><HTML><Head> <MetaCharSet= "Utf-8"> <title>Underscore & Director & Requirejs</title></Head><Body><DivID= "Container"></Div><ScriptData-baseurl="./"Data-main= "Main.js"src= "Libs/require.js"ID= "Main"></Script></Body></HTML>
There is no difference between the two articles. Requirejs introduction of Main.js as a program entry
In the second step, Main.js configures the Requirejs dependency and starts the WebApp
(function(Win) {//Configure BaseURL varBASEURL = document.getElementById (' main '). getattribute (' Data-baseurl ')); /** file Dependencies*/ varConfig ={baseurl:baseurl,//Dependent relative pathPaths: {//if the dependency of a prefix is not as simple as baseurl stitching, it needs to be pointed out hereDirector: ' Libs/director ', Zepto:' Libs/zepto.min ', underscore:' Libs/underscore ', Text:' Libs/text '//dependencies for Requirejs import of HTML types}, Shim: {//introduces a class library that does not use Requirejs module notation. underscore: {exports:‘_‘}, Zepto: {exports:$}, Director: {exports:' Router ' } } }; Require.config (config); Require ([' Zepto ', ' router ', ' underscore ',function($, router, _) {Win.appview= $ (' #container ');//for each module to control view changeswin.$ = $;//exposing the necessary global variables, no need to rigidly adhere to the requirejs of the mandatory modularityWin._ = _; Router.init (); //Start monitoring URL changes });}) (window);
Director.js does not have an AMD notation, or is introduced in the Shim way. Also, because the usage of $ and _ is too high, it is directly exposed as a global variable.
In addition, Appview variables are added to facilitate the modification of the interface for each sub-module.
Step three, Router.js configure routing
The Routing class library used here is Director (Https://github.com/flatiron/director), relatively thin routing, but in fact, for our program, it seems to be thin enough. Just do it.
The example given by the Director's official website is quite simple, which means "path" corresponds to "function", which is very clear and practical.
varAuthor =function() {Console.log ("author"); }; varBooks =function() {Console.log ("books"); }; varViewbook =function(bookId) {Console.log ("Viewbook:bookid is populated:" +bookId); }; varRoutes = { '/author ': Author,'/books ': [Books,function() {Console.log ("An inline route handler."); }], '/books/view/:bookid ': Viewbook}; varRouter =Router (routes); Router.init ();
Take a look at our own version:
Define ([' director ', ' underscore '),function(Router, _) {//first set up a Routing information table, which can be directly out of HTML, pure string configuration varRoutes = { ' Module1 ': ' Module1/controller1.js ', ' Module2/:name ': ' Module2/controller2.js '//The director has built in the common required parameters of the notation, such routes, must use the path "#module2/kenko" to match, cannot default//' module2/? ([^\/]*)/? ([^\/]*) ': ' module2/controller2.js '//can be the default parameter of the notation, in fact, is the regular expression, the brackets will be extracted from the part into the parameter value. Backbone did a better job of simplifying the grammar. //"/? ([^\/]*) "Such a paragraph represents an optional parameter that accepts any character that is not a slash/ }; varCurrentcontroller =NULL; //used to convert a string into a function, and this is the processing core of the route. varRoutehandler =function(config) {return function () { varURL =config; varparams =arguments; require ([url],function(Controller) {if(Currentcontroller && Currentcontroller!==Controller) {Currentcontroller.onroutechange&&Currentcontroller.onroutechange (); } Currentcontroller=Controller; Controller.apply (NULL, params); }); } }; for(varKeyinchroutes) {Routes[key]=Routehandler (Routes[key]); } returnRouter (routes);});
Here the director's routing configuration modified, the original can only accept <string, function> such a key value pair, but reference before backbone, the better way should be to make the table as far as possible only string configuration, do not write logic (function).
So, in the above code, there is a routehandler, the purpose is to create a closure, the string (configuration) into a closure function.
As a result, the effect is that, when a route is encountered, the corresponding submodule code is loaded according to the configuration. The subsequent actual execution of what is decided by the submodule itself. This allows the main/router to be completely decoupled from the submodule.
Fourth step, create a module
Tpl.html
<Div>Here is Module 1. My Name:<%=name%><BR> <ahref= "#module2/frommodule1">Turn to Module 2</a></Div>
Controller1.js
function (TPL) { varfunction () { ' Kenko '}); }; return Controller;});
I think that the simpler the architecture is, the better it is, the easier it is to inherit and maintain the business logic.
Controller is this sub-module to do the logic, Appview is the entire view root node, how to play on how to play, which is not familiar with angular, backbone students most cool.
The focus here is to use Requirejs for modularity and dependency loading, and underscore template Library template.
Fifth step, then do a module, plus some destruction interface
Tpl.html
<Div>Here is Module 2. My Name:<%=name%><BR> <Button>Click me!</Button> <ahref= "#module1">Turn to Module 1</a></Div>
Controller2.js
define ([' text!module2/tpl.html '),function(TPL) {varController =function(name) {appview.html (_.template (TPL, {name:name? Name: ' Vivi '})); $(' button '). On (' click ',functionClickHandler () {alert (' Hello '); }); Controller.onroutechange=function() {Console.log (' Change ');//can do some destruction work, such as canceling event binding$ (' button '). Off (' click ');//dismiss all Click event Listeners }; }; returnController;});
At this point, the entire simple framework is complete.
Boulevard to Jane, I like this simple architecture very much. Hope to be helpful to the novice friend.
Finally, about the director of the route, to spit the groove, this is not backbone those so good, it does not have built-in default parameter notation, need to understand the regular expression, write complex ([? *. Refer to the code above router.js.
The nature of route matching is actually the exec matching and extracting parameters of regular expressions. I will follow a simple and easy to use routing, refer to the backbone mode, please look forward to.
This article is code: Https://github.com/kenkozheng/HTML5_research/tree/master/UnderscoreRequireJS
A brief talk on HTML5 single page architecture (three)--return to the true: custom route + Requirejs + zepto + underscore