Backbone.js:在现实世界的应用程序中呈现集合

Posted

技术标签:

【中文标题】Backbone.js:在现实世界的应用程序中呈现集合【英文标题】:Backbone.js: rendering collections in real world apps 【发布时间】:2011-11-14 02:55:06 【问题描述】:

令人沮丧的是,backbone.js 应用程序的大多数“教程”示例都假定了一个干净的模型板。 IE。模型集合最初是空的,直到用户添加一个项目。当然,在现实世界的应用中情况并非如此,您通常从后端商店开始使用现有的集合。

我想知道人们如何处理骨干中的现有集合。具体来说:

在集合被fetched 之后如何呈现它?是否只是遍历集合的一种情况?这应该由某些事件触发吗?

主干文档谈论“引导”,我理解这意味着使用初始加载时可用的数据(从 SEO 的角度来看,这也很有意义)。但这在实践中如何运作?数据转储到服务器端的 JS 中?还是JS检查DOM?

我觉得这是一个糟糕的问题,但我希望根据答案扩展它。

编辑

所以似乎共识是将数据作为 JS 的一方添加并在页面加载时处理。

我看到这种技术的一大缺点是搜索引擎蜘蛛无法获得该信息。从这个角度来看,从 DOM 中提取它可能会更好(尽管我还没有看到有人这样做)。或者可能添加html服务器端将数据粘贴到JS中?

【问题讨论】:

有关使用 Backbone 引导的更多信息,请参阅官方文档:documentcloud.github.com/backbone/#FAQ-bootstrap @Rilely - 我已阅读文档。但是谢谢:) 【参考方案1】:

我遇到了和你一样的情况,我并不总是希望我的数据最初被引导(特别是如果它来自第三方 api 调用)。我没有遇到任何这样做的教程,但是查看文档实际上很容易。你只需要在你的集合上绑定'reset'事件(当整个集合被重新填充时触发)并渲染。这是一个简单的例子:

my_application.js

window.MyApplication = 
  Models: ,
  Collections: ,
  Views: ,
  Routers: ,
  init: function() 
    // Start the data loading
    this.someItems = new MyApplication.Collections.Items();
    this.someItems.fetch();

    // Start rendering the UI before the data is ready
    new MyApplication.Routers.Items(this.someItems);
    Backbone.history.start();
  
;

路由器/items_router.js

MyApplication.Routers.Items = Backbone.Router.extend(
  routes: 
    "" : "index"
  ,

  initialize: function(collection) 
    this.collection = collection;
  ,

  index: function() 
    var view = new MyApplication.Views.ItemsIndex( collection: this.collection );
    $('.items').html(view.render().el);
  
);

视图/项目/items_index.js

MyApplication.Views.ItemsIndex = Backbone.View.extend(
  initialize: function() 
    _.bindAll(this, "render");

    // Once the collection is fetched re-render the view
    this.collection.bind("reset", this.render);
  ,

  render: function() 
    console.log(this.collection.length);
    // Render content
    return this;
  
);

【讨论】:

【参考方案2】:

就渲染集合而言,是的,我通常会遍历集合并为每个模型创建一个子视图。这是一个可能对http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/有帮助的链接

你应该什么时候渲染它?嗯,这是一个很难回答的问题,但我不会说这是对任何特定事件的回应。我喜欢的一件事是我们有一个渲染子视图的主视图,该子视图渲染其他子视图。作为惯例,我们不直接渲染到 DOM,但是一旦所有的子视图都被渲染,我们将主视图附加到 DOM 并且整个页面立即显示。这避免了“无样式内容的闪烁”

关于引导,我从您阅读常见问题解答的内容中看到,这正是我在实践中所做的。我使用 ASP.Net MVC 3,所以我的服务器端渲染视图会有类似的东西(尽管我通常不会将“书籍”放在全局命名空间中):

<script type="text/javascript">
    books = new BooksCollection();
    books.reset(@Html.ToJson(Model));
</script>

希望对您有所帮助。

【讨论】:

我使用 ERB 或 HAML 对 Ruby on Rails 做同样的事情【参考方案3】:

实际上,我在 Backbone 上做了一些工作,我发现 Bootstrapping 数据在某些情况下确实很有帮助,当您知道在页面加载时您将需要这些数据(从而减少一个额外的 AJAX 调用)

在 Symfony 中,我通过以这种方式渲染所需数据来做到这一点:

<script type="text/template" id="__user-boostrap">
    % echo your data from php or render a controller in symfony or whatever server side script/framework you want %
    // for example in symfony2, I do:
    % render "myBundle:Core:getUser" %
</script>

现在,在 initialize() 函数中,您可以直接从 DOM 中提取这些数据,然后像往常一样开始工作:

例如,在我的路由器中,我这样做

myApp.Router = Backbone.Router.extend(
    var data = JSON.parse($('__user-bootstrap').html());
    var __games = new myApp.Games();
    __games.reset(__games.parse(data.games));
    var gameList = new myApp.GameListView( collection: __games );
    $(this.gameView).html(gameList.$el);
);

希望这会有所帮助...

【讨论】:

以上是关于Backbone.js:在现实世界的应用程序中呈现集合的主要内容,如果未能解决你的问题,请参考以下文章

backbone.js - 模板不会在asp.net视图上呈现

结合d3.js和backbone.js

Backbone.js 路由而不更改 url

Backbone js代码味道 - 更好的嵌入子视图的方法?

Backbone.js - 在视图处于活动状态时添加 keydown 事件?

使用backbone.js 从视图访问模型数据