SlideShare une entreprise Scribd logo
1  sur  116
Télécharger pour lire hors ligne
•
•
•
var Comment = Backbone.Model.extend();
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"
    }
});
•
•
•
– extend
- constructor / initialize
– get
– set
– escape
– has
– unset
– clear
– id
– cid
– attributes
– defaults
- toJSON
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;&#x2F;script&gt;
– set
– escape                     comment.has('city'); // false
– has
– unset                      comment.unset('text'); // trigger 'change' event
– clear
– id
– cid
– attributes
– defaults
- toJSON
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;&#x2F;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'
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);
                             }
                         });
•
•
•
•
•
•
var Comments = new Backbone.Collection.extend({

      model: Comment,

      initialize: function(models,options) {

      }

});
[
    {
        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
    },
    {...}
    {...}
]
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
                               });
•
•
•
•
•
•
collection.create(attributes, [options])
collection.create(attributes, [options])



var Comments = new Comments([{...}]);
collection.create(attributes, [options])



var Comments = new Comments([{...}]);




Comments.create({text: "It's no big deal!"});
collection.create(attributes, [options])



var Comments = new Comments([{...}]);




Comments.create({text: "It's no big deal!"});
collection.create(attributes, [options])



var Comments = new Comments([{...}]);




Comments.create({text: "It's no big deal!"});




var comment = new Comment({
    text: "It's no big deal!",
});

comment.save();

Comments.add(comment);
•
•
•
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();
      }
});
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);
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) { ...
});
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){ ... });

  }
•

•
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:'/'});
        },
  ...
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.
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;
        }
  });
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.
Models
Interactive Data Domain-
    specific methods
Models               Collections
Interactive Data Domain-
                           Ordered Sets of Models
    specific methods
Models               Collections
Interactive Data Domain-
                           Ordered Sets of Models
    specific methods




       Views
 Render HTML/CSS With
 Javascript templating
Models               Collections
Interactive Data Domain-
                           Ordered Sets of Models
    specific methods




       Views                    Router
 Render HTML/CSS With      Methods For Routing URL
 Javascript templating            Fragments
Models               Collections
Interactive Data Domain-
                           Ordered Sets of Models
    specific methods




       Views                    Router
 Render HTML/CSS With      Methods For Routing URL
 Javascript templating            Fragments
Models               Collections
Interactive Data Domain-
                           Ordered Sets of Models
    specific methods




       Views                    Router
 Render HTML/CSS With      Methods For Routing URL
 Javascript templating            Fragments
public/js
public/js
public/js
-- /libs/
  |- jquery.js
  |- backbone.js
  |- underscore.js
  |- json2.js
  |- mustache.js
  |- cacheprovider.js

--   /applications.js
--   /models/
--   /collections/
--   /views/
--   /controllers/
../application.js
var App = {
         Views: {},
         Router: {},
         Collections: {},
         Cache: new CacheProvider(),
         initialize: function(){
                 new App.Router.Shuo();
                 Backbone.history.start({pushState: true});
         }
     };




public/js/application.js
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
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
|-   mentions.js
|-   resharers.js
|-   results.js
|-   suggestions.js
|-   user_recommendations.js
|-   user_results.js
|-   user_timeline.js
|-   users.js
public/js/views
Home
Main
Main   Dashboard
HomeHeader




  Stream
HomeHeader
             Navigation



             Following

             Followers




             Suggestion

  Stream

                ADs

               Footer
Status


Resharers




Comments
Status


Resharers




Comments
new App.Views.StreamItem();
            model: Status
 Status     model.fetch()
            this.render()




Resharers




Comments
new App.Views.StreamItem();
            model: Status
 Status     model.fetch()
            this.render()




Resharers   new App.Views.Resharers()...




Comments
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.create()
            this.collection.remove()
...
     <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
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
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
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) {
App.initialize();
BackboneJS
MustacheJS
UnderscoreJS
BackboneJS
MustacheJS
UnderscoreJS
MustacheJS
{
    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
}
<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>
Mustache.to_html(template,data);
MustacheJS
BackboneJS
MustacheJS

UnderscoreJS
UnderscoreJS
http://shuo.douban.com/imdonkey

Contenu connexe

Tendances

Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code OrganizationRebecca Murphey
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery ApplicationsRebecca Murphey
 
Sencha Touch - Introduction
Sencha Touch - IntroductionSencha Touch - Introduction
Sencha Touch - IntroductionABC-GROEP.BE
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End DevsRebecca Murphey
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitRebecca Murphey
 
Backbone js
Backbone jsBackbone js
Backbone jsrstankov
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
Building mobile web apps with Mobello
Building mobile web apps with MobelloBuilding mobile web apps with Mobello
Building mobile web apps with MobelloJeong-Geun Kim
 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with SlimRaven Tools
 

Tendances (20)

Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
Cyclejs introduction
Cyclejs introductionCyclejs introduction
Cyclejs introduction
 
PhoneGap: Local Storage
PhoneGap: Local StoragePhoneGap: Local Storage
PhoneGap: Local Storage
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
Sencha Touch - Introduction
Sencha Touch - IntroductionSencha Touch - Introduction
Sencha Touch - Introduction
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Building mobile web apps with Mobello
Building mobile web apps with MobelloBuilding mobile web apps with Mobello
Building mobile web apps with Mobello
 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with Slim
 
Mashing up JavaScript
Mashing up JavaScriptMashing up JavaScript
Mashing up JavaScript
 

Similaire à 前端MVC 豆瓣说

Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-senseBen Lin
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
前端MVC之BackboneJS
前端MVC之BackboneJS前端MVC之BackboneJS
前端MVC之BackboneJSZhang Xiaoxue
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
Rapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageRapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageKrzysztof Bialek
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integraçãoVinícius Pretto da Silva
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015Fernando Daciuk
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentNuvole
 
ISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみたISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみたmemememomo
 
Authenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsAuthenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsJimmy Guerrero
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 

Similaire à 前端MVC 豆瓣说 (20)

Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-sense
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
前端MVC之BackboneJS
前端MVC之BackboneJS前端MVC之BackboneJS
前端MVC之BackboneJS
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Rapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirageRapid prototyping and easy testing with ember cli mirage
Rapid prototyping and easy testing with ember cli mirage
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integração
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven Development
 
ISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみたISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみた
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Authenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsAuthenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIs
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 

Dernier

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 

Dernier (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 

前端MVC 豆瓣说

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 31.
  • 32. var Comment = Backbone.Model.extend();
  • 33. 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" } });
  • 35. – extend - constructor / initialize – get – set – escape – has – unset – clear – id – cid – attributes – defaults - toJSON
  • 36. 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;&#x2F;script&gt; – set – escape comment.has('city'); // false – has – unset comment.unset('text'); // trigger 'change' event – clear – id – cid – attributes – defaults - toJSON
  • 37. 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;&#x2F;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'
  • 38. 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); } });
  • 40.
  • 42. var Comments = new Backbone.Collection.extend({ model: Comment, initialize: function(models,options) { } });
  • 43. [ { 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 }, {...} {...} ]
  • 44. 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 });
  • 49. collection.create(attributes, [options]) var Comments = new Comments([{...}]); Comments.create({text: "It's no big deal!"});
  • 50. collection.create(attributes, [options]) var Comments = new Comments([{...}]); Comments.create({text: "It's no big deal!"});
  • 51. collection.create(attributes, [options]) var Comments = new Comments([{...}]); Comments.create({text: "It's no big deal!"}); var comment = new Comment({ text: "It's no big deal!", }); comment.save(); Comments.add(comment);
  • 52.
  • 53.
  • 55.
  • 56. 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(); } });
  • 57. 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);
  • 58.
  • 59. 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) { ... });
  • 60. 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){ ... }); }
  • 62. 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:'/'}); }, ...
  • 63. 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.
  • 64. 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; } });
  • 65. 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.
  • 66.
  • 68. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods
  • 69. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Render HTML/CSS With Javascript templating
  • 70. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  • 71. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  • 72. Models Collections Interactive Data Domain- Ordered Sets of Models specific methods Views Router Render HTML/CSS With Methods For Routing URL Javascript templating Fragments
  • 75. public/js -- /libs/ |- jquery.js |- backbone.js |- underscore.js |- json2.js |- mustache.js |- cacheprovider.js -- /applications.js -- /models/ -- /collections/ -- /views/ -- /controllers/
  • 77. var App = { Views: {}, Router: {}, Collections: {}, Cache: new CacheProvider(), initialize: function(){ new App.Router.Shuo(); Backbone.history.start({pushState: true}); } }; public/js/application.js
  • 78. 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
  • 81. public/js/models |- comment.js |- comment_notification.js |- mention.js |- stat.js |- status.js |- user.js
  • 84. 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
  • 86.
  • 87. Home
  • 88.
  • 89. Main
  • 90. Main Dashboard
  • 91.
  • 93. HomeHeader Navigation Following Followers Suggestion Stream ADs Footer
  • 94.
  • 97. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers Comments
  • 98. new App.Views.StreamItem(); model: Status Status model.fetch() this.render() Resharers new App.Views.Resharers()... Comments
  • 99. 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.create() this.collection.remove()
  • 100. ... <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
  • 101. 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
  • 102. 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
  • 103. 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) {
  • 108. { 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 }
  • 109. <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>
  • 112.
  • 115.