【问题标题】:Trouble accessing attributes in the template - all attributes apart from 'name' show error '[attributename] is not defined'无法访问模板中的属性 - 除了“名称”之外的所有属性都显示错误“[属性名称] 未定义”
【发布时间】:2012-07-31 12:00:14
【问题描述】:

问题在于,当从模板访问时,除了“名称”之外的所有对象属性都会在控制台中调用错误“id/url/whatever is not defined”。只有“名称”的模板显示正常并显示正确的名称,但只要我调用不同的属性,例如。 idurl,它坏了。传递给视图的对象是一个已解析的静态 JSON 文件,其中所有项目都位于同一级别,并且可以从控制台访问,例如collectionName.models[0].get('id');

让我感到困惑的是 name 属性有效,就好像它是在骨干/下划线代码中的某个地方预定义为默认值一样。

我是否遗漏了一些非常明显的东西? 由于我可以从控制台访问模型数据,我认为视图本身处理数据的方式有问题,但我尝试用几种不同的方式重写它,似乎没有任何区别。


所有相关代码。

传递的对象格式。 这也是collectionName.models[0].attributes; 在控制台中返回的内容。

[{
"id":"0",
"name": "Building1",
"url": "building_1",
"floors":[{
    "id":"0",
    "name":"Ground Floor",
    "image":"",
    "rooms":[{
        "id": "r_1",
        "name": "Room 1",
    },
    {
        "id": "r_2",
        "name": "Room 2"
    }]
}
}]

}

示例模板代码:

<span class="name"><%= name %></span>
<%= id %> <%= url %>

路由器代码:

routes: {
  '': 'intro', // this route is using pretty much identical code and works fine, the model has the exact same format, the only difference is that all attributes work.
  ':id': 'firstLevel'    
},

firstLevel: function  (id) {
  window.singleBuilding = new ThisBuilding({}, {idBuilding: id});

  window.singleBuilding.fetch();      

  this.floorView = new FloorList({
    collection: window.singleBuilding
  });

  var $intro = $('#intro');
  $intro.empty();
  $intro.append(this.floorView.render().el);
}

观看次数:

window.FloorSingleList = Backbone.View.extend({

  className: 'floor-list',

  initialize: function  () {

  this.template = _.template(tpl.get('floors-list-item')); 
  _.bindAll(this, 'render');
  this.model.bind('change', this.render);
  this.testModel = this.model.attributes; // I tried passing the attributes directly to the templatewithout .toJSON(), which worked exactly the same, as in only the 'name' attribute worked
},

render: function  () {
  console.log("The test data is:", this.testModel);
  console.log("The actual model data is:", this.model);
  var renderedContent = this.template(this.model.toJSON());
  $(this.el).html(renderedContent);

  return this;
 }

});

window.FloorList = Backbone.View.extend({

tagName: 'section',
className: 'intro-list',

initialize: function () {

  this.template = _.template(tpl.get('intro-list'));
  _.bindAll(this, 'render');
  this.collection.bind('reset', this.render, this);
  this.collection.bind('change', this.render, this);
},

render: function  (eventName) {

     var $introList;
     var collection = this.collection;

  $(this.el).html(this.template({ }));
  $introList = this.$('.intro-list');
  collection.each(function (building) {
    var view = new FloorSingleList({
      model: building,
      collection: collection
    });
    $introList.append(view.render().el);
  });

  return this;
}

});

型号代码:

window.ThisBuilding = Backbone.Collection.extend({

model : Building,

initialize: function(models, options) {
  // Initialising the argument passed on from the router.
  this.idBuilding = options.idBuilding;
  return this;
},

url : function(){
  return  "data.json"      
},

parse: function (response) {
  console.log("Passed parameters are :", this.idBuilding); // Returns the request parameters passed from the router.
  return response[this.idBuilding];
}

});

模板和引导

// templates are loaded during the bootstrap 
tpl.loadTemplates(['header', 'intro-list', 'floors-list-item', 'building-list-item'], function() {
    window.App = new ExampleApp();
    Backbone.history.start();
});

【问题讨论】:

    标签: javascript backbone.js backbone-views backbone-routing


    【解决方案1】:

    问题在于 javascript 中的 fetch 是如何异步的......

    firstLevel: function  (id) {
      window.singleBuilding = new ThisBuilding({}, {idBuilding: id});
    
      window.singleBuilding.fetch();  // YOU FETCH HERE     
    
      this.floorView = new FloorList({
        collection: window.singleBuilding
      });
    
      var $intro = $('#intro');
      $intro.empty();
      $intro.append(this.floorView.render().el); // AND RENDER WHILE YOU CAN'T ASCERTAIN THE FETCH HAS BEEN COMPLETED...
    }
    

    所以发生的情况是渲染器尝试读取尚未正确初始化的集合 -> 您的模型尚未完成 -> 有趣的读数。在涉及异步操作时,控制台日志具有黑魔法。所以它可能会告诉你一些事情,而现实是完全不同的事情所以改为这样做:

    firstLevel: function  (id) {
      window.singleBuilding = new ThisBuilding({}, {idBuilding: id}); 
    
      // Don't fetch here...   
    
      this.floorView = new FloorList({
        collection: window.singleBuilding
      });
    
      var $intro = $('#intro');
      $intro.empty();
      $intro.append(this.floorView.el); // Don't render here
    }
    

    然后在FloorList-view:

    initialize: function () {
    
      this.template = _.template(tpl.get('intro-list'));
      _.bindAll(this, 'render');
      this.collection.bind('reset', this.render, this);
      this.collection.bind('change', this.render, this);
      this.collections.fetch(); // fetch here, your binds take care of rendering when finished
    }
    

    更新 2:显然我看到了没有复杂性的地方......忽略下面的所有内容

    来自Backbone.js docs,来自Model.toJSON()

    返回模型属性的副本以进行 JSON 字符串化。

    所以它以 JSON 格式返回属性。现在主干将id定义为

    模型的特殊属性...

    属性,而不是属性。网址也是如此。在表示主干模型的 javascript 对象中,属性存储在对象内它们自己的对象中,id 和 url 属性存储在模型对象的其他位置。例如,代表您的模型的 javascript 对象可能如下所示:

    {
      ...
      attributes: Object // this is where your name attribute lives
      ...
      id: 34, // this is your id property
      ...
      __proto__: ctor, // this is where your url-function resides
      ...
    }
    

    更新:id 属性嵌入到 model.toJSON() 中的 JSON 中

    因此,当您执行this.model.toJSON() 时,您会根据模型对象属性属性的内容创建 JSON 并包含 id 属性。 url 属性不包含在其中。例如,您可以做什么:

    var renderedContent = this.template({
      attributes: this.model.toJSON(),
      url: this.model.url()
    });
    

    在模板中

    <span class="name"><%= attributes.name %></span>
    <%= attributes.id %> <%= url %>
    

    希望这会有所帮助!

    【讨论】:

    • 感谢您的回复!似乎我对 id/url 的事情感到很困惑。 id 和 url 也是从模型传递的 JSON 响应的一部分。有关对象结构,请参阅更新后的帖子。我遇到的问题是访问这些。我可以得到名字,但不能得到 id、url 或任何不是name 的东西,即使它在属性中就在它旁边。我实际上将 JSON 文件中的 name 属性重命名为 nametest 并返回 nametest is not defined 尽管我仍然可以使用 collectionName.models[0].get('nametest') 从控制台访问它。
    • 我希望我看到的不仅仅是异步问题,但这只是异步问题。如果您的视图依赖于要正确渲染的内容,请不要在其他任何地方渲染它,除非在成功重置或来自它所依赖的资源的其他事件之后。
    • 谢谢,一切正常!我什至不认为这可能是问题所在,因为“介绍”函数在其自己的代码中的相同相对点获取数据。 'name' 属性的工作肯定让我看错了地方,但下次我会知道得更好。再次欢呼。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    相关资源
    最近更新 更多