从Backbone.View分离模板逻辑

时间:2012-02-20 17:46:48

标签: model-view-controller backbone.js javascript-framework

我刚开始学习Backbone.js,并且一直致力于(还有什么)一个简单的待办事项。在这个应用程序中,我想在<ul id="unfinished-taks"></ul>内显示我的待办事项,每个任务都是<li>元素。到目前为止,这么简单。

根据我读过的教程,我应该创建一个包含以下内容的视图:

// todo.js
window.TodoView = Backbone.View.extend({
    tagName: 'li',
    className: 'task',
    // etc...
});

这很好用,但在我的Javascript代码中定义我的待办事项的HTML标记结构似乎是不好的做法。我宁愿在模板中完全定义标记:

// todo.js
window.TodoView = Backbone.View.extend({
    template: _.template($("#template-task").html()),
    // etc...
});

<!-- todo.html -->
<script type="text/template" id="template-task">
    <li class="task <%= done ? 'done' : 'notdone' %>"><%= text %></li>
</script>

但是,如果我这样做,Backbone.js默认使用tagName: 'div'并将所有待办事项包装在无用的<div>标记中。有没有办法让HTMl标记完全包含在我的模板中而不在每个视图元素周围添加非语义<div>标记?

1 个答案:

答案 0 :(得分:1)

如果您只计划渲染一次视图,则可以在el中手动设置视图的.initialize()属性:

// todo.js
window.TodoView = Backbone.View.extend({
    template: _.template($("#template-task").html()),

    initialize: function() {
        this.el = $(this.template(this.model.toJSON())).get(0);
    },

    // etc
});

但这里有一些警告:

  • Backbone期望el属性是单个元素。我不确定如果您的模板在根目录中有多个元素会发生什么,但它可能不是您所期望的。

  • 此处重新渲染很困难,因为重新渲染模板会为您提供一个全新的DOM元素,并且您无法使用$(this.el).html()来更新现有元素。所以你必须以某种方式将新元素粘贴到旧元素的位置,这并不容易,并且可能涉及.render()中不需要的逻辑。

如果您的.render()函数不需要再次使用模板(例如,您可能使用jQuery手动更改类和文本),或者如果您不这样做,则这些不一定是show-stoppers需要重新渲染。但是如果您希望在模型更改时使用Backbone标准的“重新渲染模板”方法来更新视图,那将会很痛苦。