Successfully reported this slideshow.

【前端Mvc】之豆瓣说实践

33

Share

Upcoming SlideShare
Backbonejs for beginners
Backbonejs for beginners
Loading in …3
×
1 of 106
1 of 106

【前端Mvc】之豆瓣说实践

33

Share

Download to read offline

  1. 1. MVC [ ]
  2. 2. , “ ”
  3. 3. BackboneJS
  4. 4. UnderscoreJS MustacheJS json2 BackboneJS jQuery CacheProviderJS
  5. 5. UnderscoreJS MustacheJS BackboneJS
  6. 6. BackboneJS MustacheJS UnderscoreJS
  7. 7. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  8. 8. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  9. 9. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  10. 10. It’s a Javascript library for writing applications like....
  11. 11. It’s a Javascript library for writing applications like....
  12. 12. It’s a Javascript library for writing applications like....
  13. 13. It’s a Javascript library for writing applications like....
  14. 14. Javascript Web Application
  15. 15. Downloads & Dependencies Development Version (0.5.1) 41kb, Full Source with Comments Production Version (0.5.1) 4.6kb, Packed and Gzipped Backbone's only hard dependency is Underscore.js. For RESTful persistence, history support via Backbone.ControllerRouter and DOM manipulation with Backbone.View, include json2.js, and either jQuery ( > 1.4.2) or Zepto.
  16. 16. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  17. 17. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
  18. 18. var Comment = Backbone.Model.extend();
  19. 19. var Comment = Backbone.Model.extend(); var comment = new Comment({ id: 83562107 text: " “ ” " created_at: "2011-07-03 09:04:34" user: { uid: "keso" id: "1000185" screen_name: "keso" } });
  20. 20. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
  21. 21. comment.get('text'); // “ ” comment.set( {'text':'<script>alert('xss')</script>'}, {silent:true} ); comment.escape('text'); – extend // - constructor / initialize &lt;script&gt;alert(&#x27xss&#x27)&lt;/script&gt – get ; – set – escape comment.has('city'); // false – has – unset – clear comment.unset('text'); // trigger 'change' event – id – cid – attributes var Comment = new Backbone.Model.extend({ – defaults // hash or function() - toJSON defaults: { 'source': 'douban.com' }, initialize: function() { ... } }); var comment = new Comment(); comment.get('source'); // 'douban.com'
  22. 22. var Comment = new Backbone.Model.extend({ urlRoot: '/comment' initialize: function(attrs) { ... } }); var comment = new Comment({id:123456}); – fetch comment.url(); // '/comment/123456' – save – destroy – validate – url – urlRoot var Comment = new Backbone.Model.extend({ – parse urlRoot: '/comment' – clone initialize: function(attrs) { ... }, – isNew validate: function(attrs) { – change if ( attrs.text.length < 3 ) { – hasChanged return ' 3 ' – changedAttributes } – previous } – previousAttributes }); var comment = new Comment(); comment.set({text:'ok'},{ error: function(model,error) { alert(error); } });
  23. 23. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
  24. 24. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  25. 25. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
  26. 26. var Comments = new Backbone.Collection.extend({ model: Comment, initialize: function(models,options) { } });
  27. 27. [ { text: " “ ” " created_at: "2011-07-03 09:04:34" source: "douban.com" user: { city: " " statuses_count: 172 uid: "keso" following_count: 1688 created_at: "2005-04-07 18:01:26" followers_count: 6178 small_avatar: "http://img3.douban.com/icon/u1000185-2.jpg" id: "1000185" screen_name: "keso" ... } id: 83562107 }, {...} {...} ]
  28. 28. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
  29. 29. App.Collections.Comments = Backbone.Collection.extend({ – model – constructor / initialize model: Comment, – models initialize: function(models,options) { – toJSON – Underscore Methods (25) this.url = '/api/statuses/' + options.id + '/comments' – get + (options.count ? '?count=' + options.count : '') – getByCid + (options.page ? '&page=' + options.page : ''); this.page = 1; – at – length }, – comparator comparator: function(model) { – sort return -model.get('id'); – pluck } – url – parse });
  30. 30. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
  31. 31. User = new Backbone.Model.extend({ initialize: function(attrs) { this.url = '/users/' + attrs.id; } }); var user = new User({id: 2770683}); – add user.fetch({ – remove success:function(model,resp) { – fetch document.title = model.get('screen_name') + '/ '; – reset App.Pages.Profile = new App.Views.Profile({ model: model – create }); oBody.append(App.Pages.Profile.render().el); }, error: function(model,resp) { switch (resp.status) { case 404: App.Pages.Error = new App.Views.Error({ msg:' ' }); oBody.append(App.Pages.Error.render().el); break; } } });
  32. 32. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  33. 33. Backbone.View
  34. 34. Backbone.View • A logical UI component, not just the template • They are more like Rail’s Controller • Responsible for instantiating Collections and binding events that update the UI
  35. 35. App.Views.Comment = Backbone.View.extend({ className: 'comment-item', template: $('#comment-item-template').html(), events: { "mouseover" : "showActions", "mouseout" : "hideActions" }, initialize: function() { _.bindAll(this, 'render'); this.model.bind('change', this.render); }, render: function() { $(this.el).html(Mustache.to_html(this.template, this.model.toJSON())); $(this.el).attr({ 'data-item-id': this.model.id, 'data-comment-id': this.model.id }); return this; }, showActions: function(e) { this.$('.icon-delete').show(); }, var view = new App.Views.Comment({ hideActions: function(e) { model: model this.$('.icon-delete').hide(); }); } }); $('body').append(view.render().el);
  36. 36. Router Backbone.Controller Provides methods for routing client-side URL fragments, and connecting them to actions and events.
  37. 37. App.Router.Shuo = Backbone.Router.extend({ routes: { "" : "home", ":uid" : "profile", ":uid/following" : "following", ":uid/status/:id" : "permalink", "search/:query" : "search" }, initialize: function() { Backbone.history.start({pushState: true, root:'/'}); }, home: function() { App.Pages.Home = new App.Views.Home(); oBody.append(App.Pages.Home.render().el); this.navigate(''); }, profile: function(uid) { App.Pages.Profile[uid] = new App.Views.Profile({uid: uid}); oBody.append(App.Pages.Profile[uid].render().el); this.navigate(uid,true); }, following: function(uid) { ... permalink: function(uid,id) { ... search: function(query) { ... });
  38. 38. router.route(route, name, callback) initialize: function(options) { // Matches #page/10, passing "10" this.route("page/:number", "page", function(number){ ... }); // Matches /117-a/b/c/open, passing "117-a/b/c" this.route(/^(.*?)/open$/, "open", function(id){ ... }); }
  39. 39. Backbone.History • A global router (per frame) to handle hashchange events or pushState • Match the appropriate route, and trigger callbacks
  40. 40. Backbone.history.start([options]) App.Router.Shuo = Backbone.Router.extend({ routes: { "" : "home", ":uid" : "profile", ":uid/following" : "following", ":uid/status/:id" : "permalink", "search/:query" : "search" }, initialize: function() { Backbone.history.start({pushState: true, root:'/'}); }, ...
  41. 41. Backbone.Events ◦ "add" (model, collection) — when a model is added to a collection. ◦ "remove" (model, collection) — when a model is removed from a collection. ◦ "reset" (collection) — when the collection's entire contents have been replaced. ◦ "change" (model, collection) — when a model's attributes have changed. ◦ "change:[attribute]" (model, collection) — when a specific attribute has been updated. ◦ "destroy" (model, collection) — when a model is destroyed. ◦ "error" (model, collection) — when a model's validation fails, or a save call fails on the server. ◦ "route:[name]" (router) — when one of a router's routes has matched. ◦ "all" — this special event fires for any triggered event, passing the event name as the first argument.
  42. 42. object.bind(event, callback) App.Views.Comment = Backbone.View.extend({ className: 'comment-item', template: $('#comment-item-template').html(), initialize: function() { _.bindAll(this, 'render'); this.model.bind('change', this.render); }, render: function() { $(this.el).html(Mustache.to_html(this.template, this.model.toJSON())); $(this.el).attr({ 'data-item-id': this.model.id, 'data-comment-id': this.model.id }); return this; } });
  43. 43. Backbone.Sync Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server. By default, it uses (jQuery/Zepto).ajax to make a RESTful JSON request. You can override it in order to use a different persistence strategy, such as WebSockets, XML transport, or Local Storage.
  44. 44. Models Interactive Data Domain- specific methods
  45. 45. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods
  46. 46. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Render HTML/CSS With Javascript templating
  47. 47. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  48. 48. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  49. 49. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  50. 50. public/js
  51. 51. ../libs/ jquery.js backbone.js underscore.js json2.js mustache.js cacheprovider.js ../applications.js ../models/ ../collections/ ../views/ ../controllers/
  52. 52. ../application.js
  53. 53. var App = { Views: {}, Router: {}, Collections: {}, Cache: new CacheProvider(), initialize: function(){ new App.Controllers.Shuo(); Backbone.history.start({pushState: true}); } }; public/js/application.js
  54. 54. App.Routers.Shuo = Backbone.Router.extend({ routes: { "" : "home", "comments" : "comments", "mentions" : "mentions", ":uid" : "profile", ":uid/following" : "following", ":uid/followers" : "followers", ":uid/status/:id" : "permalink", "search/users/:query" : "user_search", "search/:query" : "search" }, initialize: function() { ... }, home: function() { ... }, comments: function() { ... }, mentions: function() { ... }, profile: function(uid) { ... }, following: function(uid) { ... }, followers: function(uid) { ... }, permalink: function(uid,id) { ... }, user_search: function(query) { ... }, search: function(query) { ... } }); public/js/controllers/shuo.js
  55. 55. public/js/models
  56. 56. public/js/models
  57. 57. public/js/models comment.js comment_notification.js mention.js recommend.js stat.js status.js user.js
  58. 58. public/js/collections
  59. 59. public/js/collections
  60. 60. public/js/collections comment_notifications.js comments.js follow_in_common.js followers.js following.js following_followers_of.js home_timeline.js likers.js mentions.js recommend_list.js resharers.js results.js suggestions.js user_recommendations.js user_results.js user_timeline.js users.js
  61. 61. public/js/views
  62. 62. Home
  63. 63. Main
  64. 64. Main Dashboard
  65. 65. HomeHeader Stream
  66. 66. HomeHeader Navigation Following Followers Suggestion Stream ADs Footer
  67. 67. Status Resharers Comments
  68. 68. Status Resharers Comments
  69. 69. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers Comments
  70. 70. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers new App.Views.Resharers()... Comments
  71. 71. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers new App.Views.Resharers()... new App.Views.Comments() this.collection = new Comments({ id: status.id Comments }); this.collection.fetch() this.collection.add() this.collection.remove()
  72. 72. ... <div id="page-outer"> </div> ... <script id="status-item-template" type="text/template">...</script> <script id="comment-item-template" type="text/template">...</script> ... template/app.html
  73. 73. App.Views.Permalink = Backbone.View.extend({ el: oDoc, item_template: $('#permalink-item-template').html(), initialize: function(options) { _.bindAll(this, 'render', 'loadStatus', 'loadResharers', 'loadLikers', 'loadComments'); var self = this; $.ajax('/api/statuses/' + options.id + '?pack=1&comment_count=50&reshare_count=14&like_count=14') .success(function(resp) { self.status = new Status(resp.status, {id: options.id}); self.comments = new App.Collections.Comments(resp.comments, {id: options.id}); self.resharers = new App.Collections.Resharers(resp.reshare_users, {id: options.id}); self.loadStatus(); }) .error(function(resp){ // 404 } }); }, render: function() { return this; }, loadStatus: function() { var view = new App.Views.StreamItem({ model: this.status }); this.loadComments(); this.loadResharers(); oPageContainer.prepend(view.render().el); }, loadResharers: function() { ... }, loadComments: function() { ... } }); public/js/views/permalink.js
  74. 74. App.initialize();
  75. 75. BackboneJS MustacheJS UnderscoreJS
  76. 76. BackboneJS MustacheJS UnderscoreJS
  77. 77. MustacheJS
  78. 78. { entities: { user_mentions: [], urls: [] } text: " “ ” " created_at: "2011-07-03 09:04:34" source: "douban.com" user: { city: " " icon_avatar: "http://img3.douban.com/icon/ui1000185-2.jpg" statuses_count: 172 uid: "keso" following_count: 1688 url: "" created_at: "2005-04-07 18:01:26" description: "keso http:// blog.donews.com/keso" followers_count: 6178 location: " " small_avatar: "http://img3.douban.com/icon/u1000185-2.jpg" following: false verified: false large_avatar: "http://img3.douban.com/icon/ul1000185-2.jpg" id: "1000185" screen_name: "keso" } id: 83562107 }
  79. 79. <script id="comment-item-template" type="text/template"> <div class="comment-item-content" data-user-id="{{#user}}{{uid}}{{/user}}" data-item-id="{{id}}" data- comment-id="{{id}}"> {{#user}} <div class="icon"> <a href="/#{{uid}}"><img src="{{small_avatar}}" alt="{{screen_name}}"/></a> </div> {{/user}} <div class="content"> <p> {{#user}} <a href="/#!/{{uid}}" class="to" title="{{uid}}">{{screen_name}}</a> {{/user}} <span class="comment-time">{{timestamp}}</span> </p> <p> <span class="comment-text">{{{text}}}</span> <a href="" class="icon-comment" title=" "><img src="http://img3.douban.com/anduin/pics/ blank.gif"/></a> </p> </div> </div> </script>
  80. 80. Mustache.to_html(template,data);
  81. 81. MustacheJS 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  82. 82. Mustache 2.0 Feature Requests
  83. 83. BackboneJS MustacheJS UnderscoreJS
  84. 84. About Me
  85. 85. : It’s no big deal!
  86. 86. End Thanks!

Editor's Notes

  • \n
  • \n
  • \n
  • &amp;#x8C46;&amp;#x74E3;&amp;#x8BF4;&amp;#x9996;&amp;#x9875;&amp;#x622A;&amp;#x56FE; &amp;#x70B9;&amp;#x51FB;&amp;#x622A;&amp;#x56FE; &amp;#x8FDE;&amp;#x63A5;&amp;#x7EBF;&amp;#x4E0A;&amp;#x771F;&amp;#x5B9E;&amp;#x73AF;&amp;#x5883; &amp;#x6F14;&amp;#x793A;&amp;#x4EE5;&amp;#x4E0B;&amp;#x51E0;&amp;#x4E2A;&amp;#x7279;&amp;#x5F81;\n1.Single Page App &amp;#x9875;&amp;#x9762;&amp;#x8DF3;&amp;#x8F6C;&amp;#x65E0;&amp;#x5237;&amp;#x65B0;\n2.History &amp;#x7BA1;&amp;#x7406;&amp;#xFF08;url&amp;#x7279;&amp;#x70B9;&amp;#xFF09;\n3.&amp;#x57FA;&amp;#x4E8E;API&amp;#x5F00;&amp;#x53D1;\n&amp;#x6709;&amp;#x8981;&amp;#x52A8;&amp;#x753B;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • \n
  • &amp;#x4E0A;&amp;#x56FE; &amp;#x5C55;&amp;#x793A;&amp;#x4EE5;&amp;#x4E0A;&amp;#x8FD9;&amp;#x90E8;&amp;#x5206;&amp;#x4EE3;&amp;#x7801;&amp;#x76F8;&amp;#x5E94;&amp;#x7684;view\n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
    1. 1. MVC [ ]
    2. 2. , “ ”
    3. 3. BackboneJS
    4. 4. UnderscoreJS MustacheJS json2 BackboneJS jQuery CacheProviderJS
    5. 5. UnderscoreJS MustacheJS BackboneJS
    6. 6. BackboneJS MustacheJS UnderscoreJS
    7. 7. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    8. 8. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    9. 9. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    10. 10. It’s a Javascript library for writing applications like....
    11. 11. It’s a Javascript library for writing applications like....
    12. 12. It’s a Javascript library for writing applications like....
    13. 13. It’s a Javascript library for writing applications like....
    14. 14. Javascript Web Application
    15. 15. Downloads & Dependencies Development Version (0.5.1) 41kb, Full Source with Comments Production Version (0.5.1) 4.6kb, Packed and Gzipped Backbone's only hard dependency is Underscore.js. For RESTful persistence, history support via Backbone.ControllerRouter and DOM manipulation with Backbone.View, include json2.js, and either jQuery ( > 1.4.2) or Zepto.
    16. 16. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    17. 17. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
    18. 18. var Comment = Backbone.Model.extend();
    19. 19. var Comment = Backbone.Model.extend(); var comment = new Comment({ id: 83562107 text: " “ ” " created_at: "2011-07-03 09:04:34" user: { uid: "keso" id: "1000185" screen_name: "keso" } });
    20. 20. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
    21. 21. comment.get('text'); // “ ” comment.set( {'text':'<script>alert('xss')</script>'}, {silent:true} ); comment.escape('text'); – extend // - constructor / initialize &lt;script&gt;alert(&#x27xss&#x27)&lt;/script&gt – get ; – set – escape comment.has('city'); // false – has – unset – clear comment.unset('text'); // trigger 'change' event – id – cid – attributes var Comment = new Backbone.Model.extend({ – defaults // hash or function() - toJSON defaults: { 'source': 'douban.com' }, initialize: function() { ... } }); var comment = new Comment(); comment.get('source'); // 'douban.com'
    22. 22. var Comment = new Backbone.Model.extend({ urlRoot: '/comment' initialize: function(attrs) { ... } }); var comment = new Comment({id:123456}); – fetch comment.url(); // '/comment/123456' – save – destroy – validate – url – urlRoot var Comment = new Backbone.Model.extend({ – parse urlRoot: '/comment' – clone initialize: function(attrs) { ... }, – isNew validate: function(attrs) { – change if ( attrs.text.length < 3 ) { – hasChanged return ' 3 ' – changedAttributes } – previous } – previousAttributes }); var comment = new Comment(); comment.set({text:'ok'},{ error: function(model,error) { alert(error); } });
    23. 23. Backbone.Model • Models contain the data • Validations,properties and permissions • Manage changes to the above
    24. 24. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    25. 25. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
    26. 26. var Comments = new Backbone.Collection.extend({ model: Comment, initialize: function(models,options) { } });
    27. 27. [ { text: " “ ” " created_at: "2011-07-03 09:04:34" source: "douban.com" user: { city: " " statuses_count: 172 uid: "keso" following_count: 1688 created_at: "2005-04-07 18:01:26" followers_count: 6178 small_avatar: "http://img3.douban.com/icon/u1000185-2.jpg" id: "1000185" screen_name: "keso" ... } id: 83562107 }, {...} {...} ]
    28. 28. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
    29. 29. App.Collections.Comments = Backbone.Collection.extend({ – model – constructor / initialize model: Comment, – models initialize: function(models,options) { – toJSON – Underscore Methods (25) this.url = '/api/statuses/' + options.id + '/comments' – get + (options.count ? '?count=' + options.count : '') – getByCid + (options.page ? '&page=' + options.page : ''); this.page = 1; – at – length }, – comparator comparator: function(model) { – sort return -model.get('id'); – pluck } – url – parse });
    30. 30. Backbone.Collection • Collections are ordered sets of models • Act on events within models • Add, Remove, Fetch, Refresh, Create, Sort
    31. 31. User = new Backbone.Model.extend({ initialize: function(attrs) { this.url = '/users/' + attrs.id; } }); var user = new User({id: 2770683}); – add user.fetch({ – remove success:function(model,resp) { – fetch document.title = model.get('screen_name') + '/ '; – reset App.Pages.Profile = new App.Views.Profile({ model: model – create }); oBody.append(App.Pages.Profile.render().el); }, error: function(model,resp) { switch (resp.status) { case 404: App.Pages.Error = new App.Views.Error({ msg:' ' }); oBody.append(App.Pages.Error.render().el); break; } } });
    32. 32. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    33. 33. Backbone.View
    34. 34. Backbone.View • A logical UI component, not just the template • They are more like Rail’s Controller • Responsible for instantiating Collections and binding events that update the UI
    35. 35. App.Views.Comment = Backbone.View.extend({ className: 'comment-item', template: $('#comment-item-template').html(), events: { "mouseover" : "showActions", "mouseout" : "hideActions" }, initialize: function() { _.bindAll(this, 'render'); this.model.bind('change', this.render); }, render: function() { $(this.el).html(Mustache.to_html(this.template, this.model.toJSON())); $(this.el).attr({ 'data-item-id': this.model.id, 'data-comment-id': this.model.id }); return this; }, showActions: function(e) { this.$('.icon-delete').show(); }, var view = new App.Views.Comment({ hideActions: function(e) { model: model this.$('.icon-delete').hide(); }); } }); $('body').append(view.render().el);
    36. 36. Router Backbone.Controller Provides methods for routing client-side URL fragments, and connecting them to actions and events.
    37. 37. App.Router.Shuo = Backbone.Router.extend({ routes: { "" : "home", ":uid" : "profile", ":uid/following" : "following", ":uid/status/:id" : "permalink", "search/:query" : "search" }, initialize: function() { Backbone.history.start({pushState: true, root:'/'}); }, home: function() { App.Pages.Home = new App.Views.Home(); oBody.append(App.Pages.Home.render().el); this.navigate(''); }, profile: function(uid) { App.Pages.Profile[uid] = new App.Views.Profile({uid: uid}); oBody.append(App.Pages.Profile[uid].render().el); this.navigate(uid,true); }, following: function(uid) { ... permalink: function(uid,id) { ... search: function(query) { ... });
    38. 38. router.route(route, name, callback) initialize: function(options) { // Matches #page/10, passing "10" this.route("page/:number", "page", function(number){ ... }); // Matches /117-a/b/c/open, passing "117-a/b/c" this.route(/^(.*?)/open$/, "open", function(id){ ... }); }
    39. 39. Backbone.History • A global router (per frame) to handle hashchange events or pushState • Match the appropriate route, and trigger callbacks
    40. 40. Backbone.history.start([options]) App.Router.Shuo = Backbone.Router.extend({ routes: { "" : "home", ":uid" : "profile", ":uid/following" : "following", ":uid/status/:id" : "permalink", "search/:query" : "search" }, initialize: function() { Backbone.history.start({pushState: true, root:'/'}); }, ...
    41. 41. Backbone.Events ◦ "add" (model, collection) — when a model is added to a collection. ◦ "remove" (model, collection) — when a model is removed from a collection. ◦ "reset" (collection) — when the collection's entire contents have been replaced. ◦ "change" (model, collection) — when a model's attributes have changed. ◦ "change:[attribute]" (model, collection) — when a specific attribute has been updated. ◦ "destroy" (model, collection) — when a model is destroyed. ◦ "error" (model, collection) — when a model's validation fails, or a save call fails on the server. ◦ "route:[name]" (router) — when one of a router's routes has matched. ◦ "all" — this special event fires for any triggered event, passing the event name as the first argument.
    42. 42. object.bind(event, callback) App.Views.Comment = Backbone.View.extend({ className: 'comment-item', template: $('#comment-item-template').html(), initialize: function() { _.bindAll(this, 'render'); this.model.bind('change', this.render); }, render: function() { $(this.el).html(Mustache.to_html(this.template, this.model.toJSON())); $(this.el).attr({ 'data-item-id': this.model.id, 'data-comment-id': this.model.id }); return this; } });
    43. 43. Backbone.Sync Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server. By default, it uses (jQuery/Zepto).ajax to make a RESTful JSON request. You can override it in order to use a different persistence strategy, such as WebSockets, XML transport, or Local Storage.
    44. 44. Models Interactive Data Domain- specific methods
    45. 45. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods
    46. 46. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Render HTML/CSS With Javascript templating
    47. 47. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
    48. 48. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
    49. 49. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
    50. 50. public/js
    51. 51. ../libs/ jquery.js backbone.js underscore.js json2.js mustache.js cacheprovider.js ../applications.js ../models/ ../collections/ ../views/ ../controllers/
    52. 52. ../application.js
    53. 53. var App = { Views: {}, Router: {}, Collections: {}, Cache: new CacheProvider(), initialize: function(){ new App.Controllers.Shuo(); Backbone.history.start({pushState: true}); } }; public/js/application.js
    54. 54. App.Routers.Shuo = Backbone.Router.extend({ routes: { "" : "home", "comments" : "comments", "mentions" : "mentions", ":uid" : "profile", ":uid/following" : "following", ":uid/followers" : "followers", ":uid/status/:id" : "permalink", "search/users/:query" : "user_search", "search/:query" : "search" }, initialize: function() { ... }, home: function() { ... }, comments: function() { ... }, mentions: function() { ... }, profile: function(uid) { ... }, following: function(uid) { ... }, followers: function(uid) { ... }, permalink: function(uid,id) { ... }, user_search: function(query) { ... }, search: function(query) { ... } }); public/js/controllers/shuo.js
    55. 55. public/js/models
    56. 56. public/js/models
    57. 57. public/js/models comment.js comment_notification.js mention.js recommend.js stat.js status.js user.js
    58. 58. public/js/collections
    59. 59. public/js/collections
    60. 60. public/js/collections comment_notifications.js comments.js follow_in_common.js followers.js following.js following_followers_of.js home_timeline.js likers.js mentions.js recommend_list.js resharers.js results.js suggestions.js user_recommendations.js user_results.js user_timeline.js users.js
    61. 61. public/js/views
    62. 62. Home
    63. 63. Main
    64. 64. Main Dashboard
    65. 65. HomeHeader Stream
    66. 66. HomeHeader Navigation Following Followers Suggestion Stream ADs Footer
    67. 67. Status Resharers Comments
    68. 68. Status Resharers Comments
    69. 69. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers Comments
    70. 70. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers new App.Views.Resharers()... Comments
    71. 71. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers new App.Views.Resharers()... new App.Views.Comments() this.collection = new Comments({ id: status.id Comments }); this.collection.fetch() this.collection.add() this.collection.remove()
    72. 72. ... <div id="page-outer"> </div> ... <script id="status-item-template" type="text/template">...</script> <script id="comment-item-template" type="text/template">...</script> ... template/app.html
    73. 73. App.Views.Permalink = Backbone.View.extend({ el: oDoc, item_template: $('#permalink-item-template').html(), initialize: function(options) { _.bindAll(this, 'render', 'loadStatus', 'loadResharers', 'loadLikers', 'loadComments'); var self = this; $.ajax('/api/statuses/' + options.id + '?pack=1&comment_count=50&reshare_count=14&like_count=14') .success(function(resp) { self.status = new Status(resp.status, {id: options.id}); self.comments = new App.Collections.Comments(resp.comments, {id: options.id}); self.resharers = new App.Collections.Resharers(resp.reshare_users, {id: options.id}); self.loadStatus(); }) .error(function(resp){ // 404 } }); }, render: function() { return this; }, loadStatus: function() { var view = new App.Views.StreamItem({ model: this.status }); this.loadComments(); this.loadResharers(); oPageContainer.prepend(view.render().el); }, loadResharers: function() { ... }, loadComments: function() { ... } }); public/js/views/permalink.js
    74. 74. App.initialize();
    75. 75. BackboneJS MustacheJS UnderscoreJS
    76. 76. BackboneJS MustacheJS UnderscoreJS
    77. 77. MustacheJS
    78. 78. { entities: { user_mentions: [], urls: [] } text: " “ ” " created_at: "2011-07-03 09:04:34" source: "douban.com" user: { city: " " icon_avatar: "http://img3.douban.com/icon/ui1000185-2.jpg" statuses_count: 172 uid: "keso" following_count: 1688 url: "" created_at: "2005-04-07 18:01:26" description: "keso http:// blog.donews.com/keso" followers_count: 6178 location: " " small_avatar: "http://img3.douban.com/icon/u1000185-2.jpg" following: false verified: false large_avatar: "http://img3.douban.com/icon/ul1000185-2.jpg" id: "1000185" screen_name: "keso" } id: 83562107 }
    79. 79. <script id="comment-item-template" type="text/template"> <div class="comment-item-content" data-user-id="{{#user}}{{uid}}{{/user}}" data-item-id="{{id}}" data- comment-id="{{id}}"> {{#user}} <div class="icon"> <a href="/#{{uid}}"><img src="{{small_avatar}}" alt="{{screen_name}}"/></a> </div> {{/user}} <div class="content"> <p> {{#user}} <a href="/#!/{{uid}}" class="to" title="{{uid}}">{{screen_name}}</a> {{/user}} <span class="comment-time">{{timestamp}}</span> </p> <p> <span class="comment-text">{{{text}}}</span> <a href="" class="icon-comment" title=" "><img src="http://img3.douban.com/anduin/pics/ blank.gif"/></a> </p> </div> </div> </script>
    80. 80. Mustache.to_html(template,data);
    81. 81. MustacheJS 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

    82. 82. Mustache 2.0 Feature Requests
    83. 83. BackboneJS MustacheJS UnderscoreJS
    84. 84. About Me
    85. 85. : It’s no big deal!
    86. 86. End Thanks!

    Editor's Notes

  • \n
  • \n
  • \n
  • &amp;#x8C46;&amp;#x74E3;&amp;#x8BF4;&amp;#x9996;&amp;#x9875;&amp;#x622A;&amp;#x56FE; &amp;#x70B9;&amp;#x51FB;&amp;#x622A;&amp;#x56FE; &amp;#x8FDE;&amp;#x63A5;&amp;#x7EBF;&amp;#x4E0A;&amp;#x771F;&amp;#x5B9E;&amp;#x73AF;&amp;#x5883; &amp;#x6F14;&amp;#x793A;&amp;#x4EE5;&amp;#x4E0B;&amp;#x51E0;&amp;#x4E2A;&amp;#x7279;&amp;#x5F81;\n1.Single Page App &amp;#x9875;&amp;#x9762;&amp;#x8DF3;&amp;#x8F6C;&amp;#x65E0;&amp;#x5237;&amp;#x65B0;\n2.History &amp;#x7BA1;&amp;#x7406;&amp;#xFF08;url&amp;#x7279;&amp;#x70B9;&amp;#xFF09;\n3.&amp;#x57FA;&amp;#x4E8E;API&amp;#x5F00;&amp;#x53D1;\n&amp;#x6709;&amp;#x8981;&amp;#x52A8;&amp;#x753B;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • \n
  • \n
  • &amp;#x4E0A;&amp;#x56FE; &amp;#x5C55;&amp;#x793A;&amp;#x4EE5;&amp;#x4E0A;&amp;#x8FD9;&amp;#x90E8;&amp;#x5206;&amp;#x4EE3;&amp;#x7801;&amp;#x76F8;&amp;#x5E94;&amp;#x7684;view\n
  • &amp;#x53EF;&amp;#x5217;&amp;#x4E3E;comments &amp;#x6216;&amp;#x8005;&amp;#x5728;status&amp;#x57FA;&amp;#x7840;&amp;#x4E0A;&amp;#x5217;&amp;#x4E3E;hometimeline&amp;#x6765;&amp;#x8BF4;&amp;#x660E;collection&amp;#x7684;&amp;#x5B9A;&amp;#x4E49;\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • &amp;#x4E0A;&amp;#x622A;&amp;#x56FE; &amp;#x5355;&amp;#x6761;&amp;#x9875;&amp;#x9762; &amp;#x5373;&amp;#x53EF; \n&amp;#x56E0;&amp;#x4E3A;&amp;#x5305;&amp;#x542B;&amp;#x4E86;model &amp;#x53CA;collection&amp;#x7684;&amp;#x5B9E;&amp;#x4F8B;\n&amp;#x4F9D;&amp;#x7167;&amp;#x622A;&amp;#x56FE; &amp;#x5206;&amp;#x6790;&amp;#x51FA;&amp;#x9875;&amp;#x9762;&amp;#x4E2D;&amp;#x7684;model&amp;#x53CA;collection\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • More Related Content

    Related Books

    Free with a 30 day trial from Scribd

    See all

    ×