【问题标题】:Backbone: Collection not rendered in View even though it's fetched主干:即使已获取集合,也不会在视图中呈现集合
【发布时间】:2014-05-04 22:01:23
【问题描述】:

我知道对此有一些问题,但答案对我来说不是很清楚。这就是为什么我再次问这个问题,以便我可以得到一个清晰而简单的答案。

我一直在 Backbone 中使用 Collection 时遇到问题,尤其是使用 JSON 数据填充它。

我似乎无法让集合在视图中呈现,即使在 firebug 中我可以看到它是从服务器获取的,但屏幕仍然是空的。 此外,当我执行console.log('callers: ', this.callerList) 时,它会返回一个带有models=[0] 的对象。但是当我展开对象时,models 充满了来自 JSON 文件的数据。 Backbone 是怎么回事,结果令人困惑?

有人可以向我解释一下怎么做吗?我已经为此奋斗了很多年,但我无法理解它。

非常感谢

JS:

(function($, window) {

  // model
  var CallerModel = Backbone.Model.extend({});

  // collection
  var CallersList = Backbone.Collection.extend({
      model: CallerModel,
      url: 'js/json/callers.json'
  });

  // view
  var CallerView = Backbone.View.extend({
      el: '.caller-app',

      template: _.template($('#callers-template').html()),

      initialize: function() {
          this.callerList = new CallersList();
          this.callerList.fetch();
          this.callerList.bind('reset', this.render);

          console.log('caller: ', this.callerList);
      },

      render: function(e) {

                  console.log('RENDER');

          _.each(this.collection.models, function(caller) {
              this.$el.append(this.template(caller.toJSON()));
                          console.log('callerList: ', caller);
          }, this);

          return this;
      }
  });

  // start
  var callerView = new CallerView();

}(jQuery, window));

HTML:

<!-- wrapper -->
<div class="wrapper">
    <h1>Missed Calls App</h1>

    <div class="caller-app"></div>

</div>
<!-- wrapper -->


<!-- templates -->
<script type="text/template" id="callers-template">
    <div class="caller">
        <h2><%= title %> <%= name %> called</h2>
        <h3>From <%= agency %></h3>
        <p>When: <%= when %></p>
        <p>Contact: <%= tel %></p>
        <p>Says:"<%= message %>"</p>
    </div>
</script>
<!-- templates -->

JSON:

[
  {
      "id": 1,
      "title": "Mrs",
      "name": "Mui",
      "agency": "Ryuzanpaku Dojo",
      "when": "evening",
      "tel": "0207 123 45 67",
      "message": "Check your availability"
  },
  {
      "id": 2,
      "title": "Mrs",
      "name": "Shigure",
      "agency": "Ryuzanpaku Dojo",
      "when": "evening",
      "tel": "0207 123 45 67",
      "message": "Check your availability"
  }
]

【问题讨论】:

  • 我没有发现任何明显的问题。我建议你在this.$el.append(this.template(caller.toJSON())); 处设置一个断点。检查调用者是否正确,以及 caller.toJSON() 返回您认为应该返回的内容。验证 this.template 是否正确,$el 是否正确等
  • 感谢@Neil 的回复。我刚刚在渲染函数中添加了一些console.log 以查看caller 内部的内容,但似乎render 甚至没有被应用。
  • 您尝试遍历集合但实际上并未分配它,此外您使用的是 this.model 而不是 this.collection。
  • 谢谢@Jack。我刚刚用你的建议更新了我的答案。但它仍然没有渲染任何东西,并且正在调用渲染函数。我认为问题比这更深,我无法弄清楚它是什么。另外你所说的集合没有分配是什么意思?
  • 我发布了一个带有 jsbin 链接的答案,请注意我是手动添加数据并调用渲染函数而不是获取它,但它应该可以正常工作。

标签: javascript html json backbone.js model-view-controller


【解决方案1】:

您实际上还没有为您的 CallerView 分配集合,此外,当您迭代集合时,您应该使用 this.collection.models 而不是 this.model.models

例如在初始化来电者列表时 初始化:函数(){

    initialize: function() {
    this.collection = new CallersList();
    this.collection.fetch();
    this.collection.bind('reset', this.render);
   }

以及渲染时

render: function(e) {

          _.each(this.collection.models, function(caller) {
              this.$el.append(this.template(caller.toJSON()));

          }, this);

          return this;
      }

这是jsbin的链接

补充几点

一般来说,您希望尽可能地解耦您的代码。为此,最好在视图之外声明和初始化您的集合,然后将其传入。这还具有使您的代码更可重用的优点,例如,假设您想呈现第二个调用列表(假设最近的调用),您现在可以创建第二个视图实例,传入集合和元素。

例如

var missedCalls = new CallersList();
var callerView = new CallerView({collection : missedCalls, el: '#missedCalls' });
missedCalls.fetch();


var recentCalls = new CallerList(); //you probably want to use a different url
var recentCallersView = new CallerView({collection : recentCalls, el:'#recentCalls'}); 
recentCalls.fetch();

还有一点值得一提,目前您正在为每次提取渲染集合中的所有项目,包括已经渲染的任何项目。您可能希望在渲染之前清空 el,或者改为监听 add 事件并在添加每个项目时单独渲染它。另外值得指出的是,fetch 并不是真正用于在页面加载时加载数据,来自documentation

请注意,不应使用 fetch 来填充页面上的集合 load - 加载时需要的所有模型都应该已经被引导 到位。 fetch 用于延迟加载模型 不需要立即使用的接口:例如,文档 带有可以打开和关闭的笔记集合。

【讨论】:

  • 谢谢@Jack。不过我还是很困惑。将集合分配给View 是什么意思?这也不能解释为什么 JSON 数据没有显示在屏幕上。我知道手动插入数据,但这次,我希望显示来自服务器的数据,因为这就是现实世界中使用的数据。现在我已经在 initiliaze 中添加了 this.render() 和来自 JSON 的数据,但它仍在工作...... :(
  • 我手动分配数据的原因只是因为它更容易在 jsbin 中设置,当您获取数据时它应该工作相同。至于将集合分配给视图,主干view 具有 model 属性和 collection 属性(两者都不是必需的,但如果您将视图用于模型,那么您将使用model 属性和collection 属性的集合。
  • 好的,我已经尝试了您的 jsbin 示例并且它有效,即手动数据,分配给 View 如下所示:var callerView = new CallerView({ collection: new CallersList });。但是,一旦我将手动数据更改为服务器数据,就不再显示任何内容。所以我认为当涉及到来自 JSON 的数据时,我的代码中没有做正确的事情???在应用来自 JSON 的数据之前,我必须做一些事情,无论是服务器还是浏览器配置,Backbone 中缺少一段代码等。这就是我想知道的,如何正确地做。
  • 显然,除非您将reset:true 传递给您的fetch,否则新版本的backbone.js 不会在您进行提取时重置集合。
  • 这取决于您的特定应用,但通常您可能希望在您的视图之外声明它并将其传递。我已经编辑了我的答案以包含有关此的更多信息。
猜你喜欢
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多