Your SlideShare is downloading. ×
0
•••
var Comment = Backbone.Model.extend();
var Comment = Backbone.Model.extend();var comment = new Comment({    id: 83562107    text: "       “   ”                  ...
•••
– extend- constructor / initialize– get– set– escape– has– unset– clear– id– cid– attributes– defaults- toJSON
comment.get(text); //       “    ”                             comment.set(                                {text:<script>a...
comment.get(text); //       “    ”                             comment.set(                                {text:<script>a...
var Comment = new Backbone.Model.extend({                             urlRoot: /comments                             initi...
•••
•••
var Comments = new Backbone.Collection.extend({      model: Comment,      initialize: function(models,options) {      }});
[    {        text: "       “   ”                 "        created_at: "2011-07-03 09:04:34"        source: "douban.com"  ...
App.Collections.Comments = Backbone.Collection.extend({–   model–   constructor / initialize         model: Comment,–   mo...
•••
•••
collection.create(attributes, [options])
collection.create(attributes, [options])var Comments = new Comments([{...}]);
collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});
collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});
collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});v...
•••
App.Views.Comment = Backbone.View.extend({      className: comment-item,      template: $(#comment-item-template).html(), ...
App.Views.Comment = Backbone.View.extend({      className: comment-item,      template: $(#comment-item-template).html(), ...
App.Router.Shuo = Backbone.Router.extend({      routes: {          ""                                          :   "home",...
router.route(route, name, callback)  initialize: function(options) {      // Matches #page/10, passing "10"      this.rout...
••
Backbone.history.start([options])  App.Router.Shuo = Backbone.Router.extend({        routes: {            ""              ...
Backbone.Events◦ "add" (model, collection) — when a model is added to a collection.◦ "remove" (model, collection) — when a...
object.bind(event, callback)  App.Views.Comment = Backbone.View.extend({        className: comment-item,        template: ...
Backbone.sync is the function that Backbone calls every time itattempts to read or save a model to the server. By default,...
ModelsInteractive Data Domain-    specific methods
Models               CollectionsInteractive Data Domain-                           Ordered Sets of Models    specific meth...
Models               CollectionsInteractive Data Domain-                           Ordered Sets of Models    specific meth...
Models               CollectionsInteractive Data Domain-                           Ordered Sets of Models    specific meth...
Models               CollectionsInteractive Data Domain-                           Ordered Sets of Models    specific meth...
Models               CollectionsInteractive Data Domain-                           Ordered Sets of Models    specific meth...
public/js
public/js
public/js-- /libs/  |- jquery.js  |- backbone.js  |- underscore.js  |- json2.js  |- mustache.js  |- cacheprovider.js--   /...
../application.js
var App = {         Views: {},         Router: {},         Collections: {},         Cache: new CacheProvider(),         in...
App.Routers.Shuo = Backbone.Router.extend({           routes: {               ""                                  :   "hom...
public/js/models
public/js/models
public/js/models|-   comment.js|-   comment_notification.js|-   mention.js|-   stat.js|-   status.js|-   user.js
public/js/collections
public/js/collections
public/js/collections|-   comments.js|-   follow_in_common.js|-   followers.js|-   home_timeline.js|-   likers.js|-   ment...
public/js/views
Home
Main
Main   Dashboard
HomeHeader  Stream
HomeHeader             Navigation             Following             Followers             Suggestion  Stream              ...
StatusResharersComments
StatusResharersComments
new App.Views.StreamItem();            model: Status Status     model.fetch()            this.render()ResharersComments
new App.Views.StreamItem();            model: Status Status     model.fetch()            this.render()Resharers   new App....
new App.Views.StreamItem();            model: Status Status     model.fetch()            this.render()Resharers   new App....
...     <div id="page-outer">     </div>     ...    <script id="status-item-template" type="text/template">...</script>   ...
App.Views.Permalink = Backbone.View.extend({        el: oDoc,        initialize: function(options) {            _.bindAll(...
App.Views.Permalink = Backbone.View.extend({       ...       loadComments: function() {           var view = new App.Views...
App.Views.Comments = Backbone.View.extend({                     className: comments-manager,                     template:...
App.initialize();
BackboneJSMustacheJSUnderscoreJS
BackboneJSMustacheJSUnderscoreJS
MustacheJS
{    entities: {        user_mentions: [],        urls: []    }    text: "       “   ”                 "    created_at: "2...
<script id="comment-item-template" type="text/template">    <div class="comment-item-content" data-user-id="{{#user}}{{uid...
Mustache.to_html(template,data);
MustacheJS
BackboneJSMustacheJSUnderscoreJS
UnderscoreJS
http://shuo.douban.com/imdonkey
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
前端MVC 豆瓣说
Upcoming SlideShare
Loading in...5
×

前端MVC 豆瓣说

11,949

Published on

Published in: Technology
4 Comments
47 Likes
Statistics
Notes
No Downloads
Views
Total Views
11,949
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
361
Comments
4
Likes
47
Embeds 0
No embeds

No notes for slide

Transcript of "前端MVC 豆瓣说"

  1. 1. •••
  2. 2. var Comment = Backbone.Model.extend();
  3. 3. 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" }});
  4. 4. •••
  5. 5. – extend- constructor / initialize– get– set– escape– has– unset– clear– id– cid– attributes– defaults- toJSON
  6. 6. comment.get(text); // “ ” comment.set( {text:<script>alert(xss)</script>}, {silent:true} );– extend comment.escape(text);- constructor / initialize // &lt;script&gt;alert(&#x27xss&#x27)– get &lt;/script&gt;– set– escape comment.has(city); // false– has– unset comment.unset(text); // trigger change event– clear– id– cid– attributes– defaults- toJSON
  7. 7. comment.get(text); // “ ” comment.set( {text:<script>alert(xss)</script>}, {silent:true} );– extend comment.escape(text);- constructor / initialize // &lt;script&gt;alert(&#x27xss&#x27)– get &lt;/script&gt;– set– escape comment.has(city); // false– has– unset comment.unset(text); // trigger change event– clear– 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
  8. 8. var Comment = new Backbone.Model.extend({ urlRoot: /comments initialize: function(attrs) { ... } }); var comment = new Comment({id:123456});– fetch comment.url(); // /comments/123456 comment.fetch();– save– destroy– validate– url– urlRoot var Comment = new Backbone.Model.extend({– parse initialize: function(attrs) { ... },– clone validate: function(attrs) {– isNew if ( attrs.text.length < 3 ) {– change return 3 – hasChanged }– changedAttributes– previous }– previousAttributes }); var comment = new Comment(); comment.set({text:ok},{ error: function(model,error) { alert(error); } });
  9. 9. •••
  10. 10. •••
  11. 11. var Comments = new Backbone.Collection.extend({ model: Comment, initialize: function(models,options) { }});
  12. 12. [ { 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 }, {...} {...}]
  13. 13. 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 });
  14. 14. •••
  15. 15. •••
  16. 16. collection.create(attributes, [options])
  17. 17. collection.create(attributes, [options])var Comments = new Comments([{...}]);
  18. 18. collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});
  19. 19. collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});
  20. 20. collection.create(attributes, [options])var Comments = new Comments([{...}]);Comments.create({text: "Its no big deal!"});var comment = new Comment({ text: "Its no big deal!",});comment.save();Comments.add(comment);
  21. 21. •••
  22. 22. App.Views.Comment = Backbone.View.extend({ className: comment-item, template: $(#comment-item-template).html(), events: { "mouseenter" : "showActions", "mouseleave" : "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(); }, hideActions: function(e) { this.$(.icon-delete).hide(); }});
  23. 23. App.Views.Comment = Backbone.View.extend({ className: comment-item, template: $(#comment-item-template).html(), events: { "mouseenter" : "showActions", "mouseleave" : "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);
  24. 24. 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) { ...});
  25. 25. 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){ ... }); }
  26. 26. ••
  27. 27. 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:/}); }, ...
  28. 28. 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.
  29. 29. 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; } });
  30. 30. Backbone.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.
  31. 31. ModelsInteractive Data Domain- specific methods
  32. 32. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods
  33. 33. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Render HTML/CSS With Javascript templating
  34. 34. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  35. 35. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  36. 36. Models CollectionsInteractive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  37. 37. public/js
  38. 38. public/js
  39. 39. public/js-- /libs/ |- jquery.js |- backbone.js |- underscore.js |- json2.js |- mustache.js |- cacheprovider.js-- /applications.js-- /models/-- /collections/-- /views/-- /controllers/
  40. 40. ../application.js
  41. 41. var App = { Views: {}, Router: {}, Collections: {}, Cache: new CacheProvider(), initialize: function(){ new App.Router.Shuo(); Backbone.history.start({pushState: true}); } };public/js/application.js
  42. 42. 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
  43. 43. public/js/models
  44. 44. public/js/models
  45. 45. public/js/models|- comment.js|- comment_notification.js|- mention.js|- stat.js|- status.js|- user.js
  46. 46. public/js/collections
  47. 47. public/js/collections
  48. 48. public/js/collections|- comments.js|- follow_in_common.js|- followers.js|- home_timeline.js|- likers.js|- mentions.js|- resharers.js|- results.js|- suggestions.js|- user_recommendations.js|- user_results.js|- user_timeline.js|- users.js
  49. 49. public/js/views
  50. 50. Home
  51. 51. Main
  52. 52. Main Dashboard
  53. 53. HomeHeader Stream
  54. 54. HomeHeader Navigation Following Followers Suggestion Stream ADs Footer
  55. 55. StatusResharersComments
  56. 56. StatusResharersComments
  57. 57. new App.Views.StreamItem(); model: Status Status model.fetch() this.render()ResharersComments
  58. 58. new App.Views.StreamItem(); model: Status Status model.fetch() this.render()Resharers new App.Views.Resharers()...Comments
  59. 59. 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.create() this.collection.remove()
  60. 60. ... <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
  61. 61. App.Views.Permalink = Backbone.View.extend({ el: oDoc, 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
  62. 62. App.Views.Permalink = Backbone.View.extend({ ... loadComments: function() { var view = new App.Views.Comments({ model: this.status, collection: this.comments }); oPageContainer.prepend(view.render().el); } });public/js/views/permalink.js
  63. 63. App.Views.Comments = Backbone.View.extend({ className: comments-manager, template: $(#comments-components-template).html(), title_template: {{#comments_count}}<h3>{{comments_count}} </h3>{{/comments_count}}, events: { "click .submit" : "submitComment", }, initialize: function(options) { _.bindAll(this,render, loadTitle, loadOne, loadAll); this.status = options.status; this.collection.bind(add, this.loadOne); this.collection.bind(remove, this.loadAll); this.collection.bind(reset, this.loadAll); }, render: function() { $(this.el).html(Mustache.to_html(this.template,{ logged_out: !shuo.loggedIn })); this.title = this.$(.comments-title); this.oBnSubmit = this.$(.submit-area input); this.comments = this.$(.comments-items); this.loadTitle(this.status.toJSON()); this.loadAll(); return this; }, loadOne: function(model) { if ( model.isNew() ) { var view = new App.Views.Comment({ model: model }); this.comments.append(view.render().el); } }, loadTitle: function(data) { this.title.html(Mustache.to_html(this.title_template,data)); }, loadAll: function() {public/js/views/comments.js }, this.collection.each(this.loadOne); create: function(e) {
  64. 64. App.initialize();
  65. 65. BackboneJSMustacheJSUnderscoreJS
  66. 66. BackboneJSMustacheJSUnderscoreJS
  67. 67. MustacheJS
  68. 68. { 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}
  69. 69. <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>
  70. 70. Mustache.to_html(template,data);
  71. 71. MustacheJS
  72. 72. BackboneJSMustacheJSUnderscoreJS
  73. 73. UnderscoreJS
  74. 74. http://shuo.douban.com/imdonkey
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×