在骨干网和木偶额外包装(Extra wrappers in Backbone and Marione

2019-06-25 18:18发布

利用骨干网和提线木偶,我创建了一个新的布局,进入我的页面上的主要内容股利。 布局看起来是这样的:

<div id='dash-sidebar'>
    <div id='dash-profile'></div>
    <div id='dash-nav'></div> 
</div>
<div id='dash-content'></div>

问题是,当我呈现布局,骨干会自动将其包装在一个div把它变成主要内容的div像在此之前:

<div id='main-content'>    
  <div>
    <div id='dash-sidebar'>
      <div id='dash-profile'></div>
       <div id='dash-nav'></div> 
    </div>
    <div id='dash-content'></div>
  </div>
</div>

我知道我可以改变标记名的元素,但有可能避免包装模板干脆而直接将其插入到页面上的主要内容股利?

Answer 1:

每个主干视图必须由一个单一的元素来表示。 您的第一HTML块具有两个元件,这就是为什么它不能由一个视图,而不在外层div第一包裹它表示。

你可以重构你的布局,包括在main-content区域呢? 然后布局的el将对应于整个外层div。

尝试另一件事是使用Backbone.View的setElement()方法来覆盖外div的创建和手动进你想在一个视图元素的HTML。 就像是:

onRender: function() {
    this.setElement( /* the HTML you want for your layout */ );
}

我不知道怎么样,如果你HTML中有两个父元素,而不只是一个通过这样的工作,但是。



Answer 2:

EDIT3:警告! 这个答案可能是过时的。 我得到的评价是这样的回答不再起作用,还没有调查(我个人不使用此方法)的时间。

我喜欢使用Twitter /引导我的UI库,并有因为默认标签包装的一些问题与表样式(具体为<div>之间我的<tbody>我的<tr> S)。

一些挖后,我发现在木偶文档东西就Region有关该如何View重视的el 。 主干构建el从各种View属性,并保持内置元素是最新的,因此它可以在任何时间呈现。 所以我想,如果view.el是父,为什么不直接使用的HTML内容? 木偶还提供了一种方法来创建一个自定义Region

我能得到的一切通过创建一个自定义的运行Region与重写open功能。 这样我可以指定我想用一个标签和那些我不换行哪些区域。 在下面的示例代码片段,创建我定做非包装RegionNowrapRegion ),并用它在我的LayoutMyLayout )为我的<tbody>我通过我的实际程序的意见创建<tr> S)。

var NowrapRegion = Marionette.Region.extend({
  open: function(view){
    this.$el.html(view.$el.html());
  }
});

var MyLayout = Marionette.Layout.extend({
  template: templates.mylayout,
  regions: {
    foo: '#foo',
    columns: '#columns', //thead
    rows: { selector: '#rows', regionType: NowrapRegion } //tbody
  }
});

繁荣! 结束语时,我想这和没有当我不知道。

编辑:这似乎影响events在应用*View水平。 我还没有研究过,但警告说,他们似乎没有被得到触发。

这是否是“正确”的方式做到这一点或没有,我不知道。 我将欢迎@德里克 - 贝利的任何反馈,他应该看到这一点。

EDIT2:@克里斯-尼尔提出以下,我还没有证实这还没有,但它似乎声音。 谢谢!

而不是复制在查看HTML,使用子节点上深克隆将保持事件和数据。

var NowrapRegion = Marionette.Region.extend({
  open: function(view){
    view.$el.children().clone(true).appendTo(this.$el);
  }
});


Answer 3:

UPDATE:Marionette.Layout是骨干观点的延伸,所以这是正常的行为,请参阅骨干文档:

在“厄尔尼诺”属性引用在浏览器中创建的DOM对象。 每个Backbone.js的观点有一个“厄尔尼诺”的属性,如果没有定义,Backbone.js的将建立自己的,这是一个空的div元素。

所以我以前的答案不得不无关,与你的问题,对不起。

更新:

发现了一个问题,546在这个问题上的骨干GitHub上(至极被关闭为wontfix),jashkenas发布此评论,解释为什么它是不容易实现:

利用骨干意见的优势有很大一部分是他们有随时可用的元素的事实 - 无论模板是否已经呈现(不少意见中有多个模板) - 无论羯羊的看法是存在于DOM与否。

这使您可以创建并添加欣赏到DOM,后来渲染,并确保您的所有活动都正确绑定(因为他们是从view.el委托)。

如果你能拿出一个好的策略,允许以拥有“完成”,同时保留上述特征模板......那么让我们来谈论它 - 但它必须允许根元素,而无需渲染的内容存在模板(这可能取决于可能无法到达,直到后来的数据),并且必须允许以轻松拥有多个模板。



Answer 4:

我想达到几乎同样的事情。 我想在我的模板中的所有HTML标记,让骨干做休息。 所以我写了下面的代码片段从而消除多余的“格”。

首先,设置标记名“检测”,然后第一渲染后你发现的第一个元素的标签名的视图中。 显然,当你在你的模板提供自己的包装这仅适用。

// Single table row inside tbody
tableRowView = Backbone.Marionette.ItemView.extend({
  tagName: 'detect',
  template: function(data) {
    return Handlebars.templates['tablerow/single'](data);
  },
  onRender: function() {
    if (this.tagName == 'detect')
      this.tagName = this.$el.children().first().prop('tagName').toLowerCase();
    this.setElement( this.$el.children( this.tagName ) );
    var $parent = this.$el.parent( this.tagName );
    if ($parent.length) {
      this.$el.detach();
      this.$el.insertAfter($parent);
      $parent.remove();
    }
  },
  modelEvents: {
    "change": "render"
  }
});

模板:

<tr>
  <td>{{artist}}</td>
  <td>{{title}}</td>
  <td>{{length}}</td>
</tr>

不过,我只是打得四处这一点 - 如果有人看到任何问题,这种做法可能会导致(性能,内存,僵尸等),我会很开放,以了解他们。

顺便说一句,这也许可以很容易地打包成一个插件。



文章来源: Extra wrappers in Backbone and Marionette