如何在Backbone中避免使用空div进行模板包装?

时间:2012-11-28 09:37:12

标签: javascript jquery backbone.js

当我创建视图主干时,如果未设置el,则创建空div容器。模板(this.$el.html(this.template(this.model.toJSON())))插入该div中。如何避免这个包装?我需要没有任何包装的干净模板,所以我可以将它插入我想要的任何地方?使用许多元素调用jobView.$e.children()是不合理的。

<script id="contactTemplate" type="text/html">
                <div class="job">
                    <h1><%= title %>/<%= type %></h1>
                    <div><%= description %></div>
                </div>     
</script>     

var JobView = Backbone.View.extend({
        template:_.template($("#contactTemplate").html()),

        initialize:function () {
            this.render();
        },
        render:function () {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
});

var jobView = new JobView({
   model:jobModel
});          

console.log(jobView.el);

6 个答案:

答案 0 :(得分:15)

我认为尚未提供此问题的真实答案,只需从模板中删除div并将className属性添加到JobView即可!这将导致您需要的标记:

模板:

<script id="contactTemplate" type="text/html">
     <h1><%= title %>/<%= type %></h1>
     <div><%= description %></div>
</script>

观点:

var JobView = Backbone.View.extend({
            className: 'job', // this class will be added to the wrapping div when you render the view

            template:_.template($("#contactTemplate").html()),

            initialize:function () {
                this.render();
            },
            render:function () {
                this.$el.html(this.template(this.model.toJSON()));
                return this;
            }
    });

当您致电render时,您将获得所需的标记:

<div class="job">
  <h1><%= title %>/<%= type %></h1>
  <div><%= description %></div>
</div>

答案 1 :(得分:8)

我认为最好的解决方案是:

render: function(){
    var html = this.template(this.model.toJSON()));
    var newElement = $(html)
    this.$el.replaceWith(newElement);
    this.setElement(newElement);
    return this;
}

答案 2 :(得分:6)

抱歉,对于迟到的回复,这可能已经解决了。我发现尽可能轻松地尝试制作模板和视图。我使用Handlebars作为我的模板。

每个模板无论使用何时都需要有一个与之关联的HTML元素,因此在您的视图中选择您想要的任何元素并从模板中删除该元素,而不是试图违背细节。然后,您可以在视图中设置属性以反映已删除模板元素的属性。

var yourview = Backbone.View.extend({
{
     tagName    : *whatever element ( i.e. section, div etc ),
     attributes : {
           id    : 'your element id'
           class : 'your element class'
           etc
     },
})

然后在你的模板中删除该元素,这个元素将很好地创建而不包装你的模板,而不必更改你的渲染方法。

答案 3 :(得分:5)

您可以将视图渲染到您喜欢的任何容器中,既可以自己指定$ el属性,也可以在调用render之前使用setElement()方法:

var jobView = new JobView({
  model:jobModel
});          

jobView.setElement($('#your_selector_here'));

console.log(jobView.el);

如果查看View.el的文档,您会发现在编写视图时也可以指定el属性,或者在构造函数中传递参数。

答案 4 :(得分:2)

我遇到了与Backbone相同的问题。在我看来,这是一个设计缺陷。这是一篇Reddit帖子,描述了一些可能的解决方案:http://www.reddit.com/r/javascript/comments/11pkth/how_do_you_render_your_backbonejs_views/

Jeremy Ashkenas对这个问题的看法是:

  

|如果我想在我的模板中完全封装HTML,而不创建任何额外的div,|我必须更换this.el.至少据我所知。有没有更好的方法呢?

     

放弃你这样做的愿望,你会有更轻松的时间;)   Backbone始终为您提供视图元素(“el”)的重要一点是,您的事件始终有效 - 无论视图是否在DOM中,数据是否已准备就绪,或者如果模板可用。声明鼠标和键盘事件是一种更无状态的方式,更少依赖于渲染所需的顺序。   如果您确实想要替换视图的元素,请使用setElement。但不建议或必要。

答案 5 :(得分:0)

无论好坏,在Backbone中,您应该使用视图提供的el,并根据您的喜好使用tagNameclassName,{{1}进行调整该视图的{和} id属性。

这种方法的一个明显问题是你混合搭配JS和HTML,就像没有明天一样。在我看来,最好把事情分开; attributes的特征应与模板一起指定。

2014年,我编写了一个旨在解决问题的插件:Backbone.Declarative.Views。它可能是我所有开源软件中最被低估的东西,但它的工作做得很好。

如何吗

Include Backbone.Declarative.Views进入您的项目。然后,将这些el - 定义属性放入模板的数据属性中。

el

现在,如果您的视图具有<script id="my-template" type="text/x-template" data-tag-name="p" data-id="myContainer" data-class-name="someClass orOther"> <!-- template content here --> </script> 属性,则其template: "#my-template"设置为

el

就是这样,真的。有关完整的详细信息,请查看the docs

为何选择数据属性?

使用数据属性解决了在HTML文件和模板中保留HTML相关内容以及Javascript之外的基本问题。同时,这种方法fully compatible与通常在Backbone中完成的方式相同。

即,所有现有的Backbone模板都可以继续正常工作,就像所有<p id="myContainer" class="someClass orOther"></p> 个定义分散在整个Javascript still get applied as usual中一样。避免了与其他Backbone扩展和插件的冲突,并且无需更改遗留代码。这使得Backbone.Declarative.Views可以安全地包含在几乎任何项目中。