Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to Backbone.js

Intro to Backbone.js

This was a presentation given to the inaugural Suncoast.js meetup group.

Tyler Johnston

December 06, 2012
Tweet

Other Decks in Technology

Transcript

  1. HI, I’M TYLER JOHNSTON I work at Spatial Networks as

    a Ruby on Rails and Javascript developer. We do cool things with maps. @tylerjohnst tylerjohnst Friday, December 7, 12
  2. WHAT IS BACKBONE.JS? • A toolkit for creating client-side Javascript

    frameworks. • Uses MVC design patterns for creating easy to maintain applications. • Supplies solutions to very common pain points when developing large front end Javascript applications: • Persisting • Event binding • Window URL changing • Organization Friday, December 7, 12
  3. WHAT ISN’T BACKBONE? • Backbone isn’t the end all be

    all Javascript tool. • Backbone will get you 80% of the way there. There are plenty of awesome Backbone plugins that will extend the functionality you might be looking for. (Storage, Relations, Widgets, etc) • Agnostic framework. Bring whatever libraries, coding style, or whatever you like to the table, Backbone doesn’t care (too much). Friday, December 7, 12
  4. WHY SHOULD I USE BACKBONE? Backbone is a great tool

    to help prevent spaghetti Javascript code. Simple jQuery plugin calls work here and there but it can quickly become a mess. Is my code like this? How would I know? Friday, December 7, 12
  5. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE Friday, December 7, 12
  6. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE Page Event Binding Friday, December 7, 12
  7. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Page Event Binding Friday, December 7, 12
  8. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Network IO Page Event Binding Friday, December 7, 12
  9. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Network IO Input parsing Page Event Binding Friday, December 7, 12
  10. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Network IO Input parsing Response parsing Page Event Binding Friday, December 7, 12
  11. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Network IO Input parsing HTML Templating Response parsing Page Event Binding Friday, December 7, 12
  12. $(document).ready(function() { $('#new-status form').submit(function(e) { e.preventDefault(); $.ajax({ url: '/status', type:

    'POST', dataType: 'json', data: { text: $('#new-status').find('textarea').val() }, success: function(data) { $('#statuses').append('<li>' + data.text + '</li>'); $('#new-status').find('textarea').val(''); }, error: function(error) { $('#error').fadeIn(); } complete: function(data) { $('.spinner').fadeOut() } }); }); }); EXAMPLE CODE User Event Binding Network IO DOM manipulation Input parsing HTML Templating Response parsing Page Event Binding Friday, December 7, 12
  13. • Backbone has one hard dependency: • A wonderful library

    that gives you access to all sorts of helpers that some browsers do not already give you access to. • Map, Reduce, Select, etc. • Compatible for all major browsers and uses ECMAscript5 functions when it can for additional performance. • Doesn’t pollute prototypes of native objects (String, Array, Object, etc). OK, HOW DO I GET STARTED? Friday, December 7, 12
  14. ANYTHING ELSE? • If you want to anything involving DOM

    manipulation (which you probably do) you must include either jQuery or Zepto. • To do anything involving third party REST APIs JSON2.js is required for IE. • All the dependancies must be loaded before Backbone is required. Friday, December 7, 12
  15. MVC? WHAT IS THAT? • Model - Business logic on

    your data models and dispatcher of notifications of changes to your data objects. Ignorant of the UI. Backbone.Model and Backbone.Collection • View - Collection of classes and elements representing the user interface. Ignorant of the business logic. Backbone.View • Controller - In between of the model and the view. Listens for notifications and fetches data from the model and displays them to the view. Backbone.View and Backbone.Router I guess I lied, it’s not really MVC, but it is a good way to describe the type of functionality that Backbone gives you. Friday, December 7, 12
  16. BACKBONE.MODEL var Tweet = Backbone.Model.extend({ defaults: { "posted_from": "TweetBot", "tweet":

    "I love twitter!", "selected": false }, initialize: function() { ... } selectTweet: function() { this.set({ selected: !this.get('selected') }); } displayName: function() { return [ this.get('first_name'), this.get('last_name') ].join(' '); }, }) var myTweet = new Tweet({ "tweet": "Dear diary..." }) Friday, December 7, 12
  17. BACKBONE.MODEL • Supports event bindings, validations, computed properties, and access

    control and persisting to an API. • Because object structures are in memory, it is much faster to read from an object than it is to crawl the DOM looking for fields. • Allows you to keep all of your business logic on your data models in a single place. Don’t put that in your views! Friday, December 7, 12
  18. BACKBONE.COLLECTION var Tweets = Backbone.Collection.extend({ model: Tweet, url: function() {

    return "http://www.twitter.com/statuses/user_timeline/" + "tylerjohnst.json?count=10" }, withHashTag: function(hashTag) { this.filter(function(tweet) { return _.indexOf(tweet.get('tweet'), hashTag) != -1 }) }, }) var TweetCollection = new Tweets TweetCollection.reset([ { "tweet": "Dear diary..." }, { "tweet": "OMG THIS CAT PICTURE!! instagr.am..." } ]) Friday, December 7, 12
  19. BACKBONE.COLLECTION • Functions as an ordered set of instances of

    Backbone models in a “smart” array. • Built in functions from Underscore that allow for easy searching, filtering, and interating through the instances of your models. • Allows for event binding on the entire collection of models and synchronizing with web APIs. • Models synced from the API will use the class that is defined in the model attribute. this.collection.each(function(model) { .. }) Friday, December 7, 12
  20. BACKBONE.SYNC • Module included in both Model and Collection. •

    The magic behind the Backbone.Model and Backbone.Collection persisting and fetching. • Uses the “URL” key from the Model definition. • Assumes your back end is a REST resource. Friday, December 7, 12
  21. BACKBONE.SYNC • If the resource you use is not a

    JSON endpoint, you must override Backbone.sync. Doing this will make Model.save() or Collection.fetch() to function properly. This function must return an XHR object. Examples of why you might do this: • XML end point • Custom parameters required • Websocket API • method is the name of the CRUD operation: create, read, update, delete. • model is the instance of your Model or Collection that is trying to persist. • options is the settings object passed from the model action. Backbone.sync = function(method, model, options) { ... }; Friday, December 7, 12
  22. BACKBONE.SYNC • Both Backbone.Model and Backbone.Collection have a parse() function

    that can be overridden to support your API. Friday, December 7, 12
  23. BACKBONE.VIEW var TweetView = Backbone.View.extend({ events: { "click .star": "selectTweet",

    "click .retweet", "retweetTweet", "click .delete", "deleteTweet" }, initialize: function() { _.bindAll('render', this); this.model.bind('change', this.render, this); }, render: function() { var html = this.template(this.model.toJSON()); this.$el.html(html); return this } selectTweet: function(event) { this.model.selectTweet(); }, retweetTweet: function(event) { ... } }) var myView = new TweetView $('body').append(myView.render().el) Friday, December 7, 12
  24. BACKBONE.VIEW • The center point of all DOM manipulation from

    within your application. • Handles HTML rendering, re-rendering, and maintaining DOM state for its own elements. • Binding events to a Model or Collection to allow for a complete separation from data and presentation. Friday, December 7, 12
  25. BACKBONE.ROUTER var tweetCenter = Backbone.Router.extend({ routes: { "help": "help" "tweet/:user/:id":

    "tweet" "": "root" }, help: function() { ... }, tweet: function(user, id) { ... }, root: function() { ... } }); window.router = new tweetCenter; Backbone.History.start(); window.router.navigate("help"); Friday, December 7, 12
  26. BACKBONE.ROUTER • Creates a ‘history’ of events for your application.

    All of which are dispatched through the routes object. • Enables back/forward button support from within your application. • Ability to use PushState with compatible browsers with graceful fallback to hashbang to non-modern browsers. • All of this is handled automatically by the Backbone.Router after Backbone.History.start() is called. Friday, December 7, 12
  27. TEMPLATING • Templates are Javascript functions that generate HTML for

    you. • While templating is not in the scope of what Backbone does, it does facilitate using a template from within the Backbone.View. • Many ways to render templates: • Mustache (Hogan, Handlebars) • EJS (Underscore, JST) • Haml Friday, December 7, 12
  28. TEMPLATING BAD This can become unmaintainable very quickly. Imagine five

    or ten attributes you need to present in this view? var html = "<ul>"; this.collection.each(function(model) { html += "<li><strong>" + model.get('user_name') + "</strong><p>" + model.get('tweet') + "</p><time>" + model.get('created_at') + "</time></li>" }); html += "</ul>"; GOOD <script type='text/template' id='myTemplate'> <li> <strong>{{user_name}}</strong> <p>{{tweet}}</p> <time>{{created_at}}</time> </li> </script> var html = $('#myTemplate').html() var template = Handlebars.compile(html); this.collection.each(function(model) { json = model.toJSON(); $('ul').append(template(json)); }; Ability to write HTML with very little markup. Clear separation of concerns and much easier to maintain. Friday, December 7, 12
  29. HOW DO I USE IT? The last part of this

    presentation I will go over some of the things I do in my code and maybe it will help you get started on your projects. Friday, December 7, 12
  30. WHAT DO I DO? twitter_app/ !"" models # $"" tweet.js

    !"" collections # $"" tweets.js !"" views # !"" tweet.js # $"" timeline.js !"" templates # !"" tweet.handlebars # $"" timeline.handlebars !"" helpers.js $"" application.js Group similar types of files together within folders to keep things organized and compartmentalized. Friday, December 7, 12
  31. HOW DO I USE IT? • I keep every view

    class to a very specific job. Within an application there can be views for many types of things. For an example a Twitter client: • View to maintain other views, act as a controller. • View to maintain a list of tweets. Each tweet will also have its own view. • Router used to set up application state and then initialize my “controller” view to set up the entire DOM. Friday, December 7, 12
  32. @tylerjohnst tylerjohnst Thanks for listening, I’ll be available afterwords to

    answer any additional questions that you may have! Friday, December 7, 12