16

当我创建视图主干时,如果未设置 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);
4

6 回答 6

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>
于 2012-11-28T12:32:13.057 回答
8

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

render: function(){
    var html = this.template(this.model.toJSON()));
    var newElement = $(html)
    this.$el.replaceWith(newElement);
    this.setElement(newElement);
    return this;
}
于 2013-07-31T15:23:27.487 回答
7

抱歉,回复晚了,这可能已经解决了。我发现最好尝试尽可能轻松地制作模板和视图。我将 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
     },
})

然后在您的模板中删除该元素,此元素将在不包装模板的情况下很好地创建,而不必更改您的渲染方法。

于 2013-09-05T21:06:39.133 回答
5

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

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

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

console.log(jobView.el);

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

于 2012-11-28T09:45:12.953 回答
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。但不推荐,也没有必要。

于 2012-11-28T09:44:45.540 回答
0

无论好坏,在 Backbone 中,您应该使用视图提供的,并使用该视图的 、和属性将其el调整为您喜欢的。tagNameclassNameidattributes

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

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

如何?

将Backbone.Declarative.Views 包含到您的项目中。然后,将这些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被设置为

<p id="myContainer" class="someClass orOther"></p>

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

为什么是数据属性?

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

也就是说,所有现有的 Backbone 模板都可以继续正常工作,就像tagName散布在 Javascript 中的所有定义仍然照常应用一样。避免了与其他 Backbone 扩展和插件的冲突,并且无需更改遗留代码。这使得 Backbone.Declarative.Views 可以安全地包含在几乎任何项目中。

于 2015-10-20T09:31:23.950 回答