Backbone.js - 从现有的HTML实例化模型/视图

14

今天我开始研究backbone.js,希望通过它更好地组织我的应用程序代码。

我想知道(概念上来说 - 所以用伪代码回答没关系),如何使用我的现有HTML创建Backbone模型(和视图)。

我发现的所有教程都是使用空白HTML模板,然后使用ajax注入内容。我不想这样做。

如果我有一本书的集合。

<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>My Book Collection</title>
</head>
<body>
    <head>

    </head>
    <body>
        <ul id="bookCollection">
            <li class="book" data-book-id="1"><input type="text" name="book_1_name" value="My Book A"/></li>
            <li class="book" data-book-id="2"><input type="text" name="book_2_name" value="My Book B"/></li>
            <li class="book" data-book-id="3"><input type="text" name="book_3_name" value="My Book C"/></li>
            <li class="book" data-book-id="4"><input type="text" name="book_4_name" value="My Book D"/></li>
            <li class="book" data-book-id="5"><input type="text" name="book_5_name" value="My Book E"/></li>
        </ul>
    </body>
</body>
</html>
在这个阶段,我想将每本书都作为一个模型来管理,在书名更改时调用一个函数(函数中仅使用警报以证明概念),然后调用URL将模型中的更改与我的数据库同步。
有人能指导我如何使用页面上现有的HTML完成上述操作吗?
如果有影响的话,我打算在模板中使用Mustache。

你的问题是关于是否需要更改你的HTML以实现这个目的吗?如果是这样:不是真的需要。还是你想要JS代码? - Bernhard Vallant
@lazerscience - 我只是想知道是否可以从现有的HTML创建视图(而不是拉取数据,使用数据+模板创建HTML,然后将其注入页面)-以及我该如何做到这一点?在上面的示例中,我是否需要创建一个循环(我正在使用jQuery),并为每个书籍元素创建一个视图? - calumbrodie
3个回答

15

我也在尝试做同样的事情,并且已经找到了解决方法!

我正在尝试构建一个待办事项列表示例,在这个页面上已经有一些待办事项,想要将它们作为模型引入到我的Todos集合中,并以与添加到空白页面中的元素相同的方式进行管理。

整个js代码都被粘贴在这里 https://gist.github.com/1255736 ,并带有注释以进行更多解释。

重要的部分是如何实例化集合。基本上:

  1. 通过jQuery获取现有的html元素。如果您的模型视图基于tagName:'li',则这是您需要在此处检索的标记类型。
  2. 遍历这些标记以抓取其中的数据,这些数据构成您的模型并创建您的模型
  3. 为每个模型创建一个视图,向其传递模型和基础元素。这是我遇到的问题:我创建了视图,然后尝试稍后通过my_view.el = xxx添加它。这不起作用。
  4. 将您的模型添加到集合中

注意:通常稍后将集合绑定到视图,以便使用collection.add将更新视图。由于initialize在构造函数中调用,因此集合尚未绑定,您不会通过在此处添加它们来重复在HTML中添加元素。

// this is the important part for initializing from html!
khepin.Todos = Backbone.Collection.extend({
    model: khepin.Todo,

    // In this function we populate the list with existing html elements
    initialize: function() {
        _.each(
            // get all the <li></li> todo items (the base for the todo view)
            // and for each of them:
            $('.todo'),
            function(a){
                // Create the model
                var todo = new khepin.Todo();
                // Find the todo's text
                var task = $(a).find('span')[0];
                task = $(task).text();
                // set the model correctly
                todo.set({
                    task: task
                });
                // create the todo view
                var todoView = new khepin.TodoView({
                    model: todo,
                    el: a // the el has to be set here. I first tried calling new TodoView and setting the 'el' afterwards
                    // and the view wasn't managed properly. We set the "el' to be the <li></li> we got from jQuery
            });
        // Add this new model to the collection
        this.add(todo);
        },
        this
    );
}
})

希望这能帮到您!

6
Backbone的视图始终绑定到特定的HTML元素(视图的属性el)。您可以将类似于BookCollectionView的内容绑定到ul#bookCollection,并将BookView绑定到li.book,这与您当前的模板结构应该很好地配合。
您可以使用模型的URL将Book模型映射到视图。如果从该URL获取了模型,并且您已经为模型更改定义了事件绑定,则相应的视图应使用新模型数据进行刷新。对于集合的URL和一组书籍也适用。
我猜没有太多关于Backbone的好教程,但是可以学习类似于http://liquidmedia.ca/blog/2011/02/backbone-js-part-3/http://www.jamesyu.org/2011/02/09/backbone.js-tutorial-with-rails-part-2/之类的内容。如果您能提出一些更具体的问题,那么可能会更容易理解!

谢谢您的回复。当您说“BookView绑定到li.book,这应该符合您当前的模板结构”时,您是指一个视图绑定到五个单独的项目吗?这样做可以吗?难道backbone不需要分别跟踪这5个项目吗?抱歉问题比较笼统 - 我只是想在入门之前掌握涉及的概念。 - calumbrodie
它将为每个 li 绑定一个单独的视图实例!每次发生这种情况时,视图中定义的所有事件也将绑定到视图的元素上,因此如果视图被重新渲染,则应定义所有事件(这是使用backbone的一个重大优势,在大多数情况下无需使用类似jQuery的live) - Bernhard Vallant
谢谢您的帮助 - 毫无疑问,将来还有更多愚蠢的问题 - calumbrodie

2

我曾经遇到过同样的问题,并通过我的主视图(ul列表)的构造函数解决了它 - 从backbone 0.9开始。

我在脑海中将其转换为coffeescript语法,如果有语法错误,请温柔一些。

myListView = Backbone.View.extend({
    initialize: function() {
        ._each(this.$el.children(), function(book, i) {
             new Backbone.View({
                  el: book,
                  model: this.collection.at(i)
             });
        });
    }
});

然后像这样调用它:

new myListView({
     collection: anExistingCollection,
     el: $('#bookCollection')
});

重要的是,“anExistingCollection”收集的顺序与您已生成的列表条目相同,因为此示例依赖于相同的索引。

(未经测试)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接