2016-09-20 1 views
0

チュートリアルYour First Backbone.js Appの次のコードに3つのconsole.logを挿入しました。ビューのどの機能が最初に実行されますか?初期化またはレンダリング?

私の質問は:なぜconsole.log(this.el)は要素のinnerHtmlが既に "レンダリング"されているが、その後にconsole.log('render runs!')メッセージが印刷されることを示していますか?

ビューのどの機能が最初に実行されますか?初期化またはレンダリング?次のようにコンソールから

$(function(){ 

    // Create a model for the services 
    var Service = Backbone.Model.extend({ 

     // Will contain three attributes. 
     // These are their default values 

     defaults:{ 
      title: 'My service', 
      price: 100, 
      checked: false 
     }, 

     // Helper function for checking/unchecking a service 
     toggle: function(){ 
      this.set('checked', !this.get('checked')); 
     } 
    }); 


    // Create a collection of services 
    var ServiceList = Backbone.Collection.extend({ 

     // Will hold objects of the Service model 
     model: Service, 

     // Return an array only with the checked services 
     getChecked: function(){ 
      return this.where({checked:true}); 
     } 
    }); 

    // Prefill the collection with a number of services. 
    var services = new ServiceList([ 
     new Service({ title: 'web development', price: 200}), 
     new Service({ title: 'web design', price: 250}), 
     new Service({ title: 'photography', price: 100}), 
     new Service({ title: 'coffee drinking', price: 10}) 
     // Add more here 
    ]); 

    // This view turns a Service model into HTML 
    var ServiceView = Backbone.View.extend({ 
     tagName: 'div', 

     events:{ 
      'click': 'toggleService' 
     }, 

     initialize: function(){ 

      // Set up event listeners. The change backbone event 
      // is raised when a property changes (like the checked field) 
      console.log(this); 
      console.log(this.el); 

      this.listenTo(this.model, 'change', this.render); 
     }, 

     render: function(){ 

      // Create the HTML 
      console.log("render runs!"); 

      this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>'); 
      this.$('input').prop('checked', this.model.get('checked')); 

      // Returning the object is a good practice 
      // that makes chaining possible 
      return this; 
     }, 

     toggleService: function(){ 
      this.model.toggle(); 
     } 
    }); 

    // The main view of the application 
    var App = Backbone.View.extend({ 

     // Base the view on an existing element 
     el: $('#main'), 

     initialize: function(){ 

      // Cache these selectors 
      this.total = $('#total span'); 
      this.list = $('#services'); 


      // Listen for the change event on the collection. 
      // This is equivalent to listening on every one of the 
      // service objects in the collection. 
      this.listenTo(services, 'change', this.render); 


      // Create views for every one of the services in the 
      // collection and add them to the page 

      services.each(function(service){ 

       var view = new ServiceView({ model: service }); 
       this.list.append(view.render().el); 

      }, this); // "this" is the context in the callback 
     }, 

     render: function(){ 

      // Calculate the total order amount by agregating 
      // the prices of only the checked elements 

      var total = 0; 

      _.each(services.getChecked(), function(elem){ 
       total += elem.get('price'); 
      }); 

      // Update the total price 
      this.total.text('$'+total); 

      return this; 

     } 

    }); 

    new App(); 

}); 

出力は次のようになります。それは、デフォルトのバックボーンのビューコンストラクタ内だとして

child {cid: "view7", model: child, $el: init[1], el: div} 
<div> 
<input type="checkbox" value="1" name="web development"> web development 
<span>$200</span></div> 
render runs! 

答えて

1

initializeは常に最初に呼び出されます。

renderは、手動で呼び出すたびに呼び出されます。

services.each(function(service) { 

    // ServiceView 'initialize' is called here. 
    var view = new ServiceView({ model: service }); 
    // ServiceView 'render' is called here. 
    this.list.append(view.render().el); 

}, this); 

レンダリング前にコンソールにelが表示されるのはなぜですか?

実際、コンソールはレンダリング前に要素を表示しませんが、コンソールで確認すると評価されます。

は簡単な例です:

var myObject = {}; 

console.log(myObject); 

myObject.test = "value"; 

あなたが推測していた場合は、空のオブジェクトが記録され、あなたは完全に間違っていないだろうと言うと思います。

Logged object being evaluated

小さな青い!

氏は述べています:左の

オブジェクトの値が記録されたときに、以下の値がちょうど今評価されたスナップショットを作成されました。

で述べたように、

"MUが短すぎる" コンソールがlive referencesが含まれているし、何もコピーされません。したがって、this.elを見るためにコンソールに着くと、console.log(this.el)が評価されたときではなく、今のところthis.elが何であるかが示されます。

+0

しかし、initialize関数の内部では、 "this.el"はすでにレンダリング関数内で生成されたstuffを含むようにレンダリングされています。これは意味をなさない。 –

+0

@ShawnChenは、後で記録されたオブジェクトを評価してコンソールがどのように役立つかを説明する私の答えの2番目の部分を確認します。最初の 'this.el'には' tagName'で示される空の 'div'しか含まれていませんが、コンソールがその要素を再評価すると最新の状態が表示されます。 –

+0

'HTMLElement'(これは' this.el')はオブジェクトであり、文字列ではありません。 –

関連する問題