Backbone.js只读集合视图呈现

时间:2012-06-28 20:27:51

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

我的问题的快速摘要:首先渲染视图包含集合中的元素,第二次渲染不包含。继续阅读详细信息......

另外值得注意的是:我确实认识到以下代码代表了快乐的路径,并且有许多潜在的错误处理代码缺失等等......这是为了简洁而故意。< / em>的

我对backbone.js很新,并且在找出实现以下场景的解决方案的正确方法时遇到了一些麻烦:

我有一个带有两个主要区域的页面,用于包含/显示将成为应用程序主要布局的呈现内容。一般来说,它看起来像这样:

-------------------------------------------
|                          |              |
|                          |              |
|         Content          |   Actions    |
|          Panel           |    Panel     |
|                          |              |
|                          |              |
|                          |              |
|                          |              |
|                          |              |
|                          |              |
-------------------------------------------

我有一个HTTP API,我正在从中获取数据,它实际上以JSON结果的形式提供各种模块的资源信息,从OPTIONS调用每个模块的基本URL。例如,对OPTIONS的{​​{1}}请求返回:

http://my/api/donor-corps

应用程序有一个我正在调用[ { "Id":0, "Name":"GetDonorCorps", "Label":"Get Donor Corps", "HelpText":"Returns a list of Donor Corps", "HttpMethod":"GET", "Url":"https://my/api/donor-corps", "MimeType":"application/json", "Resources":null } ] 的主干集合,它将是DonorCorpsCollection个对象的只读集合,可能由多个不同的主干视图呈现并以不同的方式显示应用程序的不同页面(最终......后来......目前情况并非如此)。 DonorCorpModel的{​​{1}}属性必须是对象的url属性,其初始DonorCorpsCollection结果的“GetDonorCorps”Url属性调用以获取API模块资源(如上所示)。

应用程序顶部有一个菜单栏,其中有链接,点击后会显示应用程序的各个页面。目前,应用程序中只有两个页面,“主页”页面和“预排序”页面。在“主页”视图中,两个面板中都包含占位符信息,表示用户应单击菜单栏上的链接以选择要执行的操作。当用户点击“预排序”页面链接时,我只想显示一个骨干视图,将Name呈现为动作面板中的无序列表。

我目前正在使用JavaScript module pattern来组织和封装我的应用程序代码,我的模块目前看起来像这样:

OPTIONS

Aaannnd最后,这都是使用以下HTML:

DonorCorpsCollection

到目前为止,我已经能够在第一次时点击“预排序”菜单链接。当我点击它时,它按预期呈现捐助者队列表。但是,如果我然后单击“主页”链接,然后再次单击“预排序”链接,这次我看到标题,但var myModule = (function () { // Models var DonorCorpModel = Backbone.Model.extend({ }); // Collections var DonorCorpsCollection = Backbone.Collection.extend({ model : DonorCorpModel }); // Views var DonorCorpsListView = Backbone.View.extend({ initialize : function () { _.bindAll(this, 'render'); this.template = _.template($('#pre-sort-actions-template').html()); this.collection.bind('reset', this.render); // the collection is read-only and should never change, is this even necessary?? }, render : function () { $(this.el).html(this.template({})); // not even exactly sure why, but this doesn't feel quite right this.collection.each(function (donorCorp) { var donorCorpBinView = new DonorCorpBinView({ model : donorCorp, list : this.collection }); this.$('.donor-corp-bins').append(donorCorpBinView.render().el); }); return this; } }); var DonorCorpListItemView = Backbone.View.extend({ tagName : 'li', className : 'donor-corp-bin', initialize : function () { _.bindAll(this, 'render'); this.template = _.template($('#pre-sort-actions-donor-corp-bin-view-template').html()); this.collection.bind('reset', this.render); }, render : function () { var content = this.template(this.model.toJSON()); $(this.el).html(content); return this; } }); // Routing var App = Backbone.Router.extend({ routes : { '' : 'home', 'pre-sort', 'preSort' }, initialize : function () { }, home : function () { // ... }, preSort : function () { // what should this look like?? // I currently have something like... if (donorCorps.length < 1) { donorCorps.url = _.find(donorCorpResources, function (dc) { return dc.Name === "GetDonorCorps"; }).Url; donorCorps.fetch(); } $('#action-panel').empty().append(donorCorpsList.render().el); } }) // Private members var donorCorpResources; var donorCorps = new DonorCorpsCollection(); var donorCorpsList = new DonorCorpsListView({ collection : donorCorps }); // Public operations return { Init: function () { return init(); } }; // Private operations function init () { getAppResources(); } function getAppResources () { $.ajax({ url: apiUrl + '/donor-corps', type: 'OPTIONS', contentType: 'application/json; charset=utf-8', success: function (results) { donorCorpResources = results; } }); } }(myModule || {})); 为空,其中没有列表项。 ...而且我不知道为什么或我需要采取不同的做法。我觉得我理解backbone.js观点和路由器一般,但在实践中,我显然错过了一些东西。

总的来说,这似乎是一个相当简单的场景,我不觉得我在这里做任何特别的事情,但我不能让它正常工作,似乎无法想象为什么。非常感谢协助,或至少在正确的方向上轻推。

2 个答案:

答案 0 :(得分:1)

对于DonorCorpListView,您的渲染代码看起来很奇怪 - 在您拥有任何数据之前,它看起来像是在模板化。您需要使用数据编译该模板以获取HTML输出。

因此,渲染逻辑应该像:

var template = $([get the template).html();
template.compile(this.collection.toJSON());
this.el.append(template.render());

我在这里使用了一些伪代码,因为我不确定你的模板机制是什么(我自己喜欢Handlebars)。

答案 1 :(得分:1)

所以,我在这里找到了解决方案。不确定它是最佳还是正确的解决方案,但它至少可以用于现在。

似乎有几个问题。根据Rob Conery的反馈,我开始研究用我的视图模板渲染集合的不同选项,这就是我提出的:

正如我在评论中提到的,我们正在使用Handlebars进行视图模板化,因此此代码使用该模板。

我最终将视图模板更改为:

<script id="pre-sort-actions-template" type="text/x-handlebars-template">
    <h2>Donor Corps</h2>
    <ul class="donor-corp-bins">
    {{#each list-items}}
        <li class="donor-corp-bin">{{this.Name}}</li>
    {{/each}}
    </ul>
</script>

然后,我完全删除了DonorCorpListItemView,并将DonorCorpsListView更改为现在看起来像这样:

var DonorCorpsListView = Backbone.View.extend({
    initialize : function () {
        _.bindAll(this, 'render');
        this.collection.bind('reset', this.render);
    },
    render : function () {
        var data = { 'list-items' : this.collection.toJSON() };
        var template = Handlebars.compile($('#pre-sort-actions-template').html());
        var content = template(data);
        $(this.el).html(content);

        return this;
    }
});

所以,这似乎正在起作用,正在做我现在需要做的事情。

我显然仍然需要了解JS和Backbone.js如何工作,因为 以下不能工作 (抛出错误)......我不明白为什么:

var DonorCorpsListView = Backbone.View.extend({
    initialize : function () {
        _.bindAll(this, 'render');
        this.template = Handlebars.compile($('#pre-sort-actions-template').html());
        this.collection.bind('reset', this.render);
    },
    render : function () {
        var data = { 'list-items' : this.collection.toJSON() };
        var content = this.template(data);
        $(this.el).html(content);

        return this;
    }
});

希望这会对某人有所帮助。