2016-09-20 69 views
0

我在以下代码中插入了三个console.log,代码来自教程Your First Backbone.js App视图的哪个功能首先被执行?初始化或渲染?

我的问题是:为什么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

的蓝色小!说:左

对象值快照记录时,低于价值评价刚才。

正如“万亩太短”中提到,

控制台包含live references并不会复制任何东西。所以当你到控制台看this.el时,它会告诉你this.el是什么,而不是当console.log(this.el)被评估时的情况。

+0

但在初始化函数内部,“this.el”已经被渲染为包含渲染函数内部产生的东西。这没有意义。 –

+0

@ShawnChen检查我答案的第二部分,它解释了控制台如何通过稍后评估记录的对象来尝试提供帮助。首先,'this.el'只包含'tagName'提到的空的'div',但是当控制台重新评估元素时,它会显示它的最新状态。 –

+0

请注意'HTMLElement'(this.el'是)是对象而不是字符串。 –

相关问题