Unlike its web development counterparts, JavaScript has never really provided structure in the form of a framework. Thankfully, in recent years, this has begun to change.
Today, I’d like to introduce you to Backbone.JS, a cute little library that makes the process of creating complex, interactive, and data-driven applications much easier. It provides a clean way to separate data from presentation.
Created by Jeremy Ashkenas, the JS ninja who built CoffeeScript, Backbone is an ultra-lightweight library that lets you create easy-to-maintain frontends. It's backend agnostic and works well with any modern JavaScript library you already use.
Backbone is a collection of cohesive objects, weighing under 4kb, that provides structure to your code and basically helps you build a proper MVC application in the browser. The official website describes its purpose this way:
Backbone provides structure for JavaScript-intensive applications by providing models with key-value bindings and custom events, a rich collection of enumerable function APIs, views with declarative event handling, and Connect it all to your existing application RESTful JSON interface.
Let's face it: the above is a bit difficult to parse and understand. So let’s continue deconstructing the jargon with Jeremy’s help.
When the content or state of a model changes, other objects that are subscribed to the model are notified so that they can process accordingly. Here, the view listens to changes in the model and updates itself accordingly, instead of the model having to deal with the view manually.
Backbone comes with many very useful functions for processing and working with your data. Unlike other implementations, arrays in JavaScript are fairly neutral, which can really be a hindrance when you have to deal with data.
Your days of writing spaghetti binding calls are over. You can programmatically declare which callback needs to be associated with a specific element.
Although the default method when you want to communicate with the server is to use standard AJAX calls, you can easily switch this to whatever you need. Many adapters have sprung up, covering most of the most popular ones, including Websockets and local storage.
Break it down into simpler terms:
Backbone provides a clean way to separate data from presentation. The model that handles the data is only concerned with synchronizing with the server, while the view's main responsibility is to listen for changes to the subscribed model and render HTML.
I’m guessing you might be a little confused right now, so let’s clarify a few things:
No. Their scopes are very complementary, with little overlap in functionality. Backbone handles all the higher-level abstractions, while jQuery (or a similar library) handles the DOM, normalized events, etc.
Their scope and use cases are very different, and just because you know one doesn't mean you shouldn't learn the other. As a JavaScript developer, you should know how to use both effectively.
Because often, front-end code becomes a steaming, dirty mess of nested callbacks, DOM manipulations, HTML for presentations, and other indescribable behavior.
Backbone provides a very clean and elegant way to manage this chaos.
Backbone is great for creating front-end heavy, data-driven applications. Think of the GMail interface, the new Twitter, or any other revelation of the past few years. It makes creating complex applications easier.
While you could shoehorn this into a more mainstream web page page, this is actually a library tailor-made for web applications.
Yes and no.
Yes, because like the frameworks mentioned above, this is mainly used to create complex front-ends for web applications.
What makes it different is that Backbone is very streamlined and doesn't come with additional widgets.
Backbone is very lightweight, less than 4kb.
There's also the fact that Cappuccino forces you to code in Objective-J, whereas Sproutcore's views must be declared programmatically in JS. While there's nothing wrong with either of these approaches, with Backbone, plain JavaScript can get the job done with common HTML and CSS, allowing for a gentler learning curve.
Absolutely. Not just the typical DOM access, AJAX wrapping types, but also the rest of the template and script loading types. It's very, very loosely coupled, which means you can use almost any tool with Backbone.
No, sorry. But here's something to cheer you up.
Okay, let’s put this question aside now and let’s get started!
MVC in Backbone originally stood for Models, Views, and Collections because there were no controllers in the framework. Things have since changed.
The core of Backbone consists of four main classes:
Since we are a little tight on time, we will only look at the core courses today. We'll follow up with a super simple app to demonstrate the concepts taught here, since putting it all in one article and expecting readers to parse it all would be too much.
Please stay alert over the next few weeks!
Model may have different meanings in different MVC implementations. In Backbone, a model represents a single entity—a record in a database, if you will. But there are no hard and fast rules here. From the Backbone website:
The model is the core of any JavaScript application, containing interactive data and much of the logic surrounding it: transformations, validations, computed properties, and access control.
The model simply gives you a way to read and write arbitrary properties or properties on a dataset. With this in mind, the following single line of code is perfectly usable:
var Game = Backbone.Model.extend({});
Let’s build on this.
var Game = Backbone.Model.extend({ initialize: function(){ alert("Oh hey! "); }, defaults: { name: 'Default title', releaseDate: 2011, } });
initialize
Will be triggered when the object is instantiated. Here I'm just calling attention to some silly behavior - you should probably be bootstrapping the data or doing other housekeeping in your application. I also defined a bunch of default values in case no data is passed.
Let’s take a look at how to read and write properties. But first, let's create a new instance.
// Create a new game var portal = new Game({ name: "Portal 2", releaseDate: 2011}); // release will hold the releaseDate value -- 2011 here var release = portal.get('releaseDate'); // Changes the name attribute portal.set({ name: "Portal 2 by Valve"});
If you notice get/set mutators, eat a cookie! The model's attributes cannot be read through the typical object.attribute format. You must implement getters/setters because the chance of changing the data by mistake is low.
At this time, all changes are only kept in memory. Let's make these changes permanent by talking to the server.
portal.save();
That's it. Are you expecting more? The above line of code will now send a request to your server. Keep in mind that the type of request changes intelligently. Since this is a new object, POST will be used. Otherwise, use PUT.
The Backbone model offers more functionality by default, but this should definitely get you started. Click on the documentation for more information.
Collections in Backbone are essentially just collections of models. Like the previous database analogy, a collection is the result of a query, where the result consists of many records [models]. You can define a collection like this:
var GamesCollection = Backbone.Collection.extend({ model : Game, } });
The first thing to note is that we are defining which collection of models this is. Expanding on our previous example, I made this collection a game collection.
Now you can continue to use your data as you wish. For example, let's extend this collection to add a method that returns only a specific game.
var GamesCollection = Backbone.Collection.extend({ model : Game, old : function() { return this.filter(function(game) { return game.get('releaseDate') < 2009; }); } } });
It's easy, isn't it? We only check if the game was released before 2009, and if so, return the game.
You can also directly manipulate the contents of the collection, as shown below:
var games = new GamesCollection games.get(0);
The above code snippet instantiates a new collection and then retrieves the model with ID 0. You can find an element at a specific position by referencing the index of the at method like this: game.at(0);
Finally, you can populate your collection dynamically like this:
var GamesCollection = Backbone.Collection.extend({ model : Game, url: '/games' } }); var games = new GamesCollection games.fetch();
We just tell Backbone where to get the data from via the url property. Once done, we simply create a new object and call the fetch method, which triggers an asynchronous call to the server and populates the collection with the results.
This should cover the basics of Backbone collections. As I mentioned, there's a ton of good stuff here, with Backbone aliasing a lot of nifty utilities from the Underscore library. A quick read of the official documentation should get you started.
At first glance, views in Backbone can be a little confusing. To MVC purists, they resemble controllers rather than views themselves.
Views fundamentally handle two responsibilities:
Let's continue creating a very simple view.
GameView= Backbone.View.extend({ tagName : "div", className: "game", render : function() { // code for rendering the HTML for the view } });
If you've been following this tutorial so far, it's pretty simple. I just specify which HTML element should be used to wrap the view via the tagName attribute, and its ID via the className.
让我们继续进行渲染部分。
render : function() { this.el.innerHTML = this.model.get('name'); //Or the jQuery way $(this.el).html(this.model.get('name')); }
el 指的是视图引用的 DOM 元素。我们只是通过元素的 innerHTML 属性访问游戏的名称。简而言之,div 元素现在包含我们游戏的名称。显然,如果您以前使用过该库,则 jQuery 方式会更简单。
对于更复杂的布局,在 JavaScript 中处理 HTML 不仅乏味而且鲁莽。在这些情况下,模板是可行的方法。
Backbone 附带了由 Underscore.JS 提供的最小模板解决方案,但我们非常欢迎您使用任何可用的优秀模板解决方案。
最后我们看一下视图是如何监听事件的。首先是 DOM 事件。
events: { 'click .name': 'handleClick' }, handleClick: function(){ alert('In the name of science... you monster'); // Other actions as necessary }
如果您以前处理过事件,那么应该很简单。我们基本上是通过事件对象定义和连接事件。正如您在上面看到的,第一部分指的是事件,下一部分指定触发元素,最后一部分指应触发的函数。
现在绑定到模型和集合。我将在这里介绍模型的绑定。
GameView= Backbone.View.extend({ initialize: function (args) { _.bindAll(this, 'changeName'); this.model.bind('change:name', this.changeName); }, });
首先要注意的是我们如何将绑定代码放置在初始化函数中。当然,最好从一开始就这样做。
bindAll 是 Underscore 提供的一个实用程序,用于保存函数的 this 值。这特别有用,因为我们传递了一堆函数,并且指定为回调的函数已删除该值。
现在,只要模型的 name 属性发生更改,就会调用 changeName 函数。您还可以使用添加和删除动词来轮询更改。
侦听集合中的更改就像将处理程序绑定到回调时将模型替换为集合一样简单。
Backbone 中的控制器本质上允许您使用 hashbang 创建可添加书签的有状态应用程序。
var Hashbangs = Backbone.Controller.extend({ routes: { "!/": "root", "!/games": "games", }, root: function() { // Prep the home page and render stuff }, games: function() { // Re-render views to show a collection of books }, });
这对于传统服务器端 MVC 框架中的路由非常熟悉。例如,!/games 将映射到 games 函数,而浏览器本身中的 URL 将是 domain/#!/games。
通过智能使用 hashbang,您可以创建大量基于 JS 且可添加书签的应用程序。
如果您担心破坏后退按钮,Backbone 也能满足您的需求。
// Init the controller like so var ApplicationController = new Controller; Backbone.history.start();
通过上面的代码片段,Backbone 可以监控您的 hashbang,并结合您之前指定的路线,使您的应用程序可添加书签。
总的来说,以下是我从创建应用程序的 Backbone 方式中学到的一些经验教训:
可以说 Backbone 引起了前端构建方式的范式转变,至少对我来说是这样。鉴于今天文章的范围非常广泛,我确信您有很多问题。点击下面的评论部分来插话。非常感谢您的阅读,并期待将来有更多的 Backbone 教程!
The above is the detailed content of Starting with Backbone.js. For more information, please follow other related articles on the PHP Chinese website!