前端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 豆瓣说
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);
                             }
                         });
•
•
•
前端MVC 豆瓣说
•
•
•
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);
前端MVC 豆瓣说
前端MVC 豆瓣说
•
•
•
前端MVC 豆瓣说
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);
前端MVC 豆瓣说
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.
前端MVC 豆瓣说
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
前端MVC 豆瓣说
Home
前端MVC 豆瓣说
Main
Main   Dashboard
前端MVC 豆瓣说
HomeHeader




  Stream
HomeHeader
             Navigation



             Following

             Followers




             Suggestion

  Stream

                ADs

               Footer
前端MVC 豆瓣说
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
前端MVC 豆瓣说
BackboneJS
MustacheJS

UnderscoreJS
UnderscoreJS
前端MVC 豆瓣说
http://shuo.douban.com/imdonkey

More Related Content

PDF
Be RESTful (Symfony Camp 2008)
PDF
Virtual Madness @ Etsy
PDF
Symfony CoP: Form component
KEY
Advanced jQuery
PDF
CQRS and Event Sourcing in a Symfony application
PDF
How I started to love design patterns
PPTX
PDF
Decoupling with Design Patterns and Symfony2 DIC
Be RESTful (Symfony Camp 2008)
Virtual Madness @ Etsy
Symfony CoP: Form component
Advanced jQuery
CQRS and Event Sourcing in a Symfony application
How I started to love design patterns
Decoupling with Design Patterns and Symfony2 DIC

What's hot (20)

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

Similar to 前端MVC 豆瓣说 (20)

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

Recently uploaded (20)

PPTX
The various Industrial Revolutions .pptx
PPT
What is a Computer? Input Devices /output devices
PDF
Architecture types and enterprise applications.pdf
PPT
Geologic Time for studying geology for geologist
PDF
Hybrid model detection and classification of lung cancer
PDF
Taming the Chaos: How to Turn Unstructured Data into Decisions
PDF
Hindi spoken digit analysis for native and non-native speakers
PDF
sustainability-14-14877-v2.pddhzftheheeeee
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PDF
August Patch Tuesday
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
Unlock new opportunities with location data.pdf
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
PPTX
Web Crawler for Trend Tracking Gen Z Insights.pptx
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PPTX
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
The various Industrial Revolutions .pptx
What is a Computer? Input Devices /output devices
Architecture types and enterprise applications.pdf
Geologic Time for studying geology for geologist
Hybrid model detection and classification of lung cancer
Taming the Chaos: How to Turn Unstructured Data into Decisions
Hindi spoken digit analysis for native and non-native speakers
sustainability-14-14877-v2.pddhzftheheeeee
A comparative study of natural language inference in Swahili using monolingua...
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
August Patch Tuesday
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
Enhancing emotion recognition model for a student engagement use case through...
Unlock new opportunities with location data.pdf
A novel scalable deep ensemble learning framework for big data classification...
How ambidextrous entrepreneurial leaders react to the artificial intelligence...
Web Crawler for Trend Tracking Gen Z Insights.pptx
Final SEM Unit 1 for mit wpu at pune .pptx
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx

前端MVC 豆瓣说

  • 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); } });
  • 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);
  • 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);
  • 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.
  • 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
  • 87. Home
  • 89. Main
  • 90. Main Dashboard
  • 93. HomeHeader Navigation Following Followers Suggestion Stream ADs Footer
  • 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>