1. Introduction
Recently I am doing front-end optimization for a large-scale online banking project, which requires the use of a thick client. The general idea is that the front-end requests data through Ajax to the back-end, returns it in Jason format, and then displays it on the page. Since this system is very large, the thick client solution inevitably requires writing a lot of JS code on the client side. I think it is very inconvenient for any team to maintain a large amount of unstructured code. So BackBone came into my sight.
It provides a way for you to structure your JS code and organize your front-end JS code in an object-oriented manner. This is like applying Domain Driven Design to the front end. We can divide a very large project into modules. Each module can be divided into View, Model, and Router according to BackBone's requirements.
Through backbone, you can treat your data as Models. Through Models, you can create data, perform data validation, destroy or save to the server. When operations on the interface cause changes to attributes in the model, the model will trigger the change event; the views used to display the model status will receive the change message triggered by the model, then issue a corresponding response, and re-render the new data to interface. In a complete backbone application, you don't need to write glue code to get nodes from the DOM by special ids, or manually update the HTML page, because the views will simply update themselves when the model changes.
2. Features
Backbone is a lightweight front-end framework that is used to structurally manage a large amount of JS in pages, establish seamless connections with servers and views, and provide a basic framework for building complex applications.
Let me briefly explain the main features and characteristics of Backbone:
2.1 Lightweight
Backbone’s source code is only about 1,000 lines (after removing comments and blank lines), and the file size is only 16KB. Including the dependent library Underscore, it is only 29KB.
You only need to spend a little time to easily understand the internal implementation of Backbone; or write a small amount of code to override some of Backbone's mechanisms; if you want to do secondary development based on Backbone, it is not a complicated matter.
2.2 Structure
Backbone can easily decouple the data, logic, and views in the page, and organize the code structure according to Backbone. You can allocate the data interaction, business logic, user interface, etc. work in the project to multiple colleagues for simultaneous development. And can be organized together in an orderly manner. At the same time, this is very helpful for maintenance and development of large and complex projects.
2.3 Inheritance Mechanism
In Backbone, modules can be inherited. You can organize the data models, collections, and views in the application in an object-oriented manner to make the entire architecture clearer; you can also easily overload and extend it. Custom method.
2.4 Establish a seamless connection with the server
Backbone has a set of interaction rules with server data built in (if you understand the REST architecture, you can easily understand them), and the data synchronization work will be automatically performed in the Model, and the front-end developer only needs to When you perform operations on client data, Backbone will automatically synchronize the operated data to the server.
This is a very interesting thing because the server data interface is transparent to front-end developers, and they no longer need to worry about how to interact with the server.
However, the data interface provided by the server also needs to be compatible with Backbone's rules. For a new project, we can try to use this set of rules to build the interface. But if your project already has a stable set of interfaces, you may be worried about the risks of interface modification.
It doesn't matter, we can adapt to the existing data interface by overloading the Backbone.sync method. We can also implement different data interaction methods for different client environments. For example: when users use services through a PC browser, the data will be synchronized to the server in real time; and when users use services through mobile terminals, considering network environment issues, we can first synchronize the data to the local database, and then synchronize it to the server at the appropriate time. server. And these can be achieved by just overloading a method.
2.5 Interface event management
In MVC, we hope to completely separate the interface presentation and business logic. However, for user-generated interactive events (such as click events), we often obtain and bind them through the bind method in jQuery.
Views in Backbone help us organize user events and execution methods in an orderly manner, which only requires us to declare a simple expression, such as:
events: { // 单击id为”save”的元素时,执行视图的add方法 'click #save': 'add', 'mousedown .button': 'show', 'mouseover .button': 'hide' }
在表达式中,事件名称可以是任意的DOM事件(如click、mouseover、keypress等),元素可以是jQuery支持的任意选择器(如标签选择器、id选择器、class选择器等)。
视图会自动将表达式中的事件绑定到选择器元素,当元素的事件被触发后,视图会自动调用表达式中绑定的方法。
2.6 轻量级模板解析
模板解析是Underscore中提供的一个方法。为什么我要在介绍Backbone特性时引入Underscore中的方法?因为该方法能帮助我们更好地分离视图结构和逻辑,且Underscore是Backbone必须依赖的库。
模板解析方法能允许我们在HTML结构中混合嵌入JS代码,就像在JSP页面中嵌入Java代码一样:
<ul> <% for(var i = 0; i < len; i++) { %> <li><%=data[i].title%></li> <% } %> </li>
通过模板解析,我们不需要在动态生成HTML结构时拼接字符串,更重要的是,我们可以将视图中的HTML结构独立管理(例如:不同的状态可能会显示不同的HTML结构,我们可以定义多个单独的模板文件,按需加载和渲染即可)。
2.7 自定义事件管理
在Backbone中,你可以使用on或off方法绑定和移除自定义事件。在任何地方,你都可以使用trigger方法触发这些绑定的事件,所有绑定过该事件的方法都会被执行,如:
var model = new Backbone.Model(); // 在model对象中向自定义事件custom绑定两个函数 model.on('custom', function(p1, p2) { // todo }); model.on('custom', function(p1, p2) { // todo }); // 触发custom事件,将调用上面绑定的两个函数 model.trigger('custom', 'value1', 'value2'); // 移除custom事件中绑定的所有方法 model.off('custom'); // 触发custom事件,但不会执行任何函数,已经事件中的函数已经在上一步被移除 model.trigger('custom');
如果你熟悉jQuery,你会发现它们与jQuery中的bind、unbind和trigger方法非常类似。
另外,Backbone支持一个特殊事件”all”,当在一个对象中绑定了名为”all”的事件后,该对象在触发任何事件时,都会同时触发”all”事件中绑定的方法。有时这种方法会非常有用,例如我们可以通过”all”事件监听对象状态的变化。
3.路由器
在单页应用中,我们通过JavaScript来控制界面的切换和展现,并通过AJAX从服务器获取数据。
可能产生的问题是,当用户希望返回到上一步操作时,他可能会习惯性地使用浏览器“返回”和“前进”按钮,而结果却是整个页面都被切换了,因为用户并不知道他正处于同一个页面中。
对于这个问题,我们常常通过Hash(锚点)的方式来记录用户的当前位置,并通过onhashchange事件来监听用户的“前进”和“返回”动作,但我们发现一些低版本的浏览器(例如IE6)并不支持onhashchange事件。
Backbone提供了路由控制功能,通过Backbone提供的路由器,我们能通过一个简单的表达式将路由地址和事件函数绑定在一起,例如:
var CustomRouter = Backbone.Router.extend({ routes : { '' : 'index', // 当URL Hash在根目录时执行index方法:url# 'list' : 'getList', // 当URL Hash在list节点时执行getList方法:url#list 'detail/:id' : 'query', // 当URL Hash在detail节点时执行query方法,并将detail后的数据作为参数传递给query方法:url#list/1001 '*error' : 'showError' // 当URL Hash不匹配以上规则时, 执行error方法 }, index : function() { alert('index'); }, getList : function() { alert('getList'); }, query : function(id) { alert('query id: ' + id); }, showError : function(error) { alert('error hash: ' + error); }, }); var custom = new CustomRouter(); Backbone.history.start();
请尝试将这段代码复制到你的页面中,并依次访问以下地址(其中URL表示你的页面地址):
URL URL#list URL#detail/1001 URL#hash1 URL#hash2
Please try again using the browser's "Back" and "Forward" buttons to switch back and forth between the addresses you just entered.
You can see that when the URL Hash changes, the bound method will be executed. When an undefined Hash is encountered, the showError method will be executed and the undefined Hash will be passed to this method.
Backbone will record address changes through Hash by default. For lower version browsers that do not support onhashchange, it will monitor Hash changes through setInterval heartbeat, so you don't have to worry about browser compatibility issues.
For browsers that support the HTML5 pushState feature, Backbone also allows you to create personalized URLs through pushState, but this requires some adaptations on your web server.
3. Applicability of Backbone
Backbone is not as adaptable as jQuery. If you are preparing to build a large or complex single-page web application, then Backbone is perfect.
If you want to apply Backbone to your website page, and the page does not have complex logic and structure, then it will only make your page more cumbersome and difficult to maintain.
If your project is not complex, but you really like a certain feature of it (maybe the data model, view management, or router), then you can extract this part of the source code from Backbone, because in Backbone, each The dependencies between modules are not very strong, and you can easily obtain and use one of the modules.
4. Dependent libraries
You cannot use Backbone independently because its basic functions, DOM operations, and AJAX all rely on third-party libraries.
4.1 Underscore
(required)
Underscore is a basic function library used to improve development efficiency. It encapsulates common operations on collections, arrays, objects, and functions. Just like jQuery encapsulates DOM objects, you can easily access and operate JavaScript internal objects through Underscore.
Underscore also provides some very practical function methods, such as function throttling, template parsing, etc.
Regarding some of the main methods in Underscore, I will introduce it in detail in the next chapter, but before that you must understand: Underscore is a library that Backbone must rely on, because many implementations in Backbone are based on Underscore.
4.2 jQuery and Zepto
(optional)
I believe you are familiar with jQuery. It is a cross-browser DOM and AJAX framework.
For Zepto, you can think of it as the "mobile version of jQuery" because it is smaller, faster, and more suitable for running on the browser of mobile terminal devices. It has the same syntax as jQuery, so you can use it like jQuery.
Zepto currently only supports Webkit-based browsers, so it is compatible with most mobile systems such as iOS, Adnroid, Symbian, Blackberry, and Meego. However, it does not yet support Windows Phone or Firefox OS.
Because jQuery and Zepto have the same syntax, for Backbone, there is no problem whether you use jQuery or Zepto (of course, you can't use both at the same time).
In Backbone, DOM selectors, DOM events and AJAX all use jQuery methods. The reason why they are optional here is that if you are not using the views and AJAX data synchronization functions in Backbone, then you do not need to import them.
If you don't want to use jQuery or Zepto, but use another or custom library, there will be no problem as long as your library implements the same DOM selectors, event management, and AJAX methods as jQuery syntax.
Backbone allows you to dynamically configure the third-party libraries you need to use through the setDomLibrary method. This situation is often used:
Although your custom library contains methods with the same syntax as jQuery, the global variables are not $, and you want to keep the existing naming. At this time you can set it to the object referenced internally by Backbone through the setDomLibrary method.
You want to decide which library is more appropriate to use by examining the user's environment. For example: If the user accesses via a PC browser, jQuery is loaded; if the user accesses via a mobile terminal, Zepto is loaded.