Backbone.js 单个集合项视图

Posted

技术标签:

【中文标题】Backbone.js 单个集合项视图【英文标题】:Backbone.js single collection item view 【发布时间】:2014-12-30 16:32:53 【问题描述】:

我最近开始构建我的第一个 Backbone.js 项目,并且很难掌握如何处理单个项目的“单个视图”。

例如,如果我有一个由 Backbone 集合显示的 todos 列表。如果我想让应用程序提供单个待办事项的链接和视图,我该怎么做?我会创建一种新类型的集合并以某种方式通过单个项目的 id 过滤集合吗?这个逻辑在哪里?在路由器内?

编辑

我已经更新了我的路由器:

var Backbone = require('backbone');
var IndexListing = require('./indexlisting');
var BookView = require('./bookview');
var LibraryCollection = require('./library');

module.exports = Backbone.Router.extend(

  routes: 
    '': 'allBooks',
    'book/:id': 'singleBook'
  ,
  allBooks: function()
    new IndexListing(
      el: '#main',
      collection: LibraryCollection
    ).render();
  ,
  singleBook: function(bookID)
    console.log(bookID);
    new BookView(
      el: '#main',
      collection: LibraryCollection.get(bookID)
    ).render();
  

);

bookID 直接来自我的 MongoDB ID 并在 console.log 内返回,但是当我尝试在浏览器中运行它时出现以下错误:Uncaught TypeError: undefined is not a function 指的是 collection: LibraryCollection.get(bookID)

我的 LibraryCollection (./library) 包含以下内容:

'use strict';

 var Backbone = require('backbone');
 var Book = require('./book');

 module.exports = Backbone.Collection.extend(
   model: Book,
   url: '/api/library'
 );

我的 GET 请求的两个端点都返回以下内容:

/api/library/

["_id":"54a38070bdecad02c72a6ff4","name":"Book Name One","_id":"54a38070bdecad02c72a6ff5","name":"Book Name Two","_id":"54a38070bdecad02c72a6ff6","name":"Book Name Three","_id":"54a38070bdecad02c72a6ff7","name":"Book Name Four"]

/api/library/54a38070bdecad02c72a6ff4

"_id":"54a38070bdecad02c72a6ff4","name":"Book Name One"

编辑 2

我已经为singleBook 更新了我的路由器,如下所示:

singleBook: function(id)
var lib = new LibraryCollection;
lib.fetch(
  success: function()
    book = lib.get(id);
    new BookView(
      el: '#main',
      model: book
    ).render();
  
);

【问题讨论】:

【参考方案1】:

我真的推荐 codeschool 骨干课程 here 来介绍骨干。

您将拥有一组模型(待办事项)。每个 todo 都有自己的视图并显示模型数据,即 todo 描述。您可能希望有一个包装视图,也称为集合视图,它将每个视图都作为一个子视图,但在开始时最好不要这样做。

关于路由器逻辑,尝试将路由器中的功能视为控制器操作(假设您熟悉 MVC)。有许多主干扩展可以创建类似 MVC 控制器的功能。

对于您的问题,您可以在使用模板引擎渲染视图时在视图中创建链接。想到的一些引擎是Underscore、Handlebars和Mustache。模板可能如下所示:

<a href="/todos/ id "> description </a>

在这个模板中,我们传入模型,在花括号之间,您可以看到我们正试图提取该模型的 id 和描述。输出模型属性可能如下所示:


    id: 1,
    description: "Go shopping"

如果您只想获得一个模型,则需要确保该模型具有urlRoot 属性集。然后你需要像这样获取模型:

var singleTodo = new Todo(id: 1);
singleTodo.fetch();

正如我之前所说,我真的建议您在深入了解应用程序之前先观看一些关于骨干网的优秀教程。祝你好运!

【讨论】:

【参考方案2】:

我猜你的意思是你试图导航到一个显示单个待办事项的页面?如果是,则逻辑将存在于路由器中

var TodosRouter = Backbone.Router.extend(
  routes: 
   "todo": "allTodos"
   "todo/:todoId": "singleTodo"
   ,
  allTodos: function() 
    // assume you have a todo listing view named TodoListing, extended from Backbone.View
    // which the view inside has the link to click and navigate to #todo/<todoId>
    var view = new TodoListing(
      el: $('body'),
      collection: YourTodosCollection
    ).render();
  ,
  singleTodo: function(todoId) 
    // assume you have a todo single view named TodoView, extended from Backbone.View
    var view = new TodoView(
      el: $('body'),
      model: YourTodosCollection.get(todoId)
    ).render();
  
);

根据编辑 2 更新

是的,这可行,但它需要从数据库中获取整个集合,然后只显示单个模型,这可能会消耗大量网络资源/浏览器内存性能。

在我看来,将书的 ID 传递给 BookView 是很好的,然后我们从那里获取一本书(假设我们有一个 REST GET 调用以 ID 作为参数的一本书)。

var BookView = Backbone.View.extend(
  render: function () ...,
  initialize: function(option) 
    this.model.fetch(); // fetch only single book, with the bookId passed below
    //alternative - we do not pass the model option at below, we could parse the bookId from the router's since it will be part of param in URL eg: http://xxxx/book/:bookId, then we can do the below
    this.model = new BookModel(id: parsedFromRouter);
    this.model.fetch();
  
);

new BookView(
  el: '#main',
  model: new BookModel(id: bookId) 
).render();

fetch 调用应该是异步的,所以我们可能想要显示一些加载指示器,并且只在 fetch 完成时渲染视图

this.model.fetch(
  success: function ()  //call render 
)

【讨论】:

所以我要对集合执行 get 操作? 是的,条件是您的集合中的每个模型都具有有效的 Id 属性(对于新模型,通常 Id 为空,并且期望服务器端在之后提供新的 Id通过 REST 保存模型)。集合上的get 是使用ID backbone doc从集合中获取模型 我继续尝试实施您的解决方案,但遇到了一些问题。请参阅上面的编辑。有什么想法吗? 当然。见上文。 让我们尝试导出一个实例 module.exports = new Backbone.Collection.extend( model: Book, url: '/api/library' )();... 然后获取集合在将其提供给 TodoListing / TodoView 视图之前......无论如何这里的流程有点令人困惑......假设在 TodoView 中,您可以只传递 todoId 的 ID,然后启动 Book 模型并触发设置 ID 后的 fetch。

以上是关于Backbone.js 单个集合项视图的主要内容,如果未能解决你的问题,请参考以下文章

Backbone.js - 按顺序插入新的视图项

将集合绑定到 Backbone.js 中的视图

Backbone.js — 匿名视图实例中的集合在获取时多次请求

Backbone.js:清除所有视图的最佳方法

渲染 Backbone.js 集合

模型和集合到 Backbone 中的一个视图