Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

【前端Mvc】之豆瓣说实践

  • Soyez le premier à commenter

【前端Mvc】之豆瓣说实践

  1. 1. MVC[ ]
  2. 2. ,“ ”
  3. 3. BackboneJS
  4. 4. UnderscoreJSMustacheJS json2 BackboneJS jQuery CacheProviderJS
  5. 5. UnderscoreJSMustacheJS BackboneJS
  6. 6. BackboneJSMustacheJSUnderscoreJS
  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 & DependenciesDevelopment Version (0.5.1) 41kb, Full Source with CommentsProduction Version (0.5.1) 4.6kb, Packed and GzippedBackbones only hard dependency is Underscore.js.For RESTful persistence, history support via Backbone.ControllerRouter andDOM 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.ControllerProvides methods for routing client-side URLfragments, and connecting them to actionsand 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 collections entire contents have been replaced.◦ "change" (model, collection) — when a models 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 models validation fails, or a save call fails on the server.◦ "route:[name]" (router) — when one of a routers 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.SyncBackbone.sync is the function that Backbone calls every time itattempts to read or save a model to the server. By default, it uses(jQuery/Zepto).ajax to make a RESTful JSON request. You canoverride it in order to use a different persistence strategy, such asWebSockets, XML transport, or Local Storage.
  44. 44. ModelsInteractive Data Domain- specific methods
  45. 45. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods
  46. 46. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Render HTML/CSS With Javascript templating
  47. 47. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  48. 48. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  49. 49. Models CollectionsInteractive 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/modelscomment.jscomment_notification.jsmention.jsrecommend.jsstat.jsstatus.jsuser.js
  58. 58. public/js/collections
  59. 59. public/js/collections
  60. 60. public/js/collectionscomment_notifications.jscomments.jsfollow_in_common.jsfollowers.jsfollowing.jsfollowing_followers_of.jshome_timeline.jslikers.jsmentions.jsrecommend_list.jsresharers.jsresults.jssuggestions.jsuser_recommendations.jsuser_results.jsuser_timeline.jsusers.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. StatusResharersComments
  68. 68. StatusResharersComments
  69. 69. new App.Views.StreamItem(); model: Status Status model.fetch() this.render()ResharersComments
  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.idComments }); 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. BackboneJSMustacheJSUnderscoreJS
  76. 76. BackboneJSMustacheJSUnderscoreJS
  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. BackboneJSMustacheJSUnderscoreJS
  84. 84. About Me
  85. 85. : It’s no big deal!
  86. 86. EndThanks!

×