我将从一个明确的问题开始,然后再解释:
如何将包含在 CompositeView
中的模型正确封装到 ItemView
我的问题很简单,但我无法设法使某些东西正常工作。
我有一棵笔记树。
每个笔记都是一个 Backbone.model 并且有一个 @descendants
集合,
然后我有一个 Backbone.Collection 来表示那棵树(@descendants 是其中的一个实例)
我设置了一个基本的 CollectionView
,作为 itemView
,CompositeView
。一切都完美呈现,我对此感到非常高兴。这个有效的解决方案显示在第一段代码中!
问题来了。在此基础上,我遇到了这个问题:Events fired for whole hierarchy 这对于我的事件如何绑定(bind)是有意义的。起初,我只是添加了独特的选择器(将 data-guid 添加到我的 html 元素中,以便我可以通过它获取它们)并且它工作正常,尽管它已经变得“hacky”了。但是其他类似的问题已经出现,所以我决定我需要一个解决方案。 所以,我告诉 myslef,让我们将每个模型封装在一个 ItemView 中,并使用 Composite View 递归地渲染它们。 但是……这并不是世界上最好的……
这是我一开始的内容:
class Note.ModelView extends Marionette.CompositeView
template: "note/noteModel"
id: "note-item"
itemViewContainer: ".note-descendants"
ui:
noteContent: ".noteContent"
events:
"keypress .noteContent": "createNote"
"click .destroy": "deleteNote"
# ...
initialize: ->
@collection = @model.descendants
# ...
class Note.CollectionView extends Marionette.CollectionView
id: "note-list"
itemView: Note.ModelView
initialize: ->
@listenTo @collection, "sort", @render
现在我将所有属于渲染模型的东西转移到一个新的 ItemView 中
class Note.ModelView extends Marionette.ItemView
template: "note/noteModel"
ui:
noteContent: ".noteContent"
events: ->
guid = @model.get 'guid'
events = {}
events["keypress #noteContent#{guid}"] = "createNote"
events["blur #noteContent#{guid}"] = "updateNote"
events["click #destroy#{guid}"] = @triggerEvent 'deleteNote'
initialize: ->
@bindKeyboardShortcuts()
@listenTo @model, "change:created_at", @setCursor
class Note.TreeView extends Marionette.CompositeView
template: "note/parentNote"
itemView: Note.ModelView
initialize: ->
@collection = @model.descendants
@listenTo @collection, "sort", @render
_.bindAll @, "renderItem"
renderItem: (model) ->
if model.get('parent_id') is 'root'
itemView = new Note.ModelView model: model
itemView.render()
@$el.append itemView.el
onRender: ->
@collection.each this.renderItem
@renderItem @model
appendHtml: (collectionView, itemView) ->
@model.descendants.each (note) =>
iv = new Note.ModelView model: note
iv.render()
@.$('.note-descendants').append iv.el
class Note.CollectionView extends Marionette.CollectionView
id: "note-list"
itemView: Note.TreeView
initialize: ->
@listenTo @collection, "sort", @render
和 noteMode 模板(parentNote 现在只是一个空模板)
<button class="btn btn-danger btn-xs untab">UN</button>
<button class="btn btn-success btn-xs tab">TAB</button>
<div class="noteContent">{{{indent}}}{{{title}}}</div>
<button class="destroy"></button>
<div class="note-descendants"></div> # That is where I'm putting the children notes
所以这几乎是可行的。但它很老套而且..它仍然不太管用。我一直在阅读所有文档,并且我已经阅读了这两个链接 Derick Bailey on nested structure and CompositeView和 David Sulc on Nested Views但我仍然觉得我遗漏了一些重要的细节。
作为答案,我正在寻找的是使用 Marionette 进行管理的任何提示或任何常用方法。我真的在寻找干净的东西,因为这将成为应用程序构建的 Angular 之一。
也许我也在错误的地方搜索?什么都欢迎!!非常感谢
祝大家度过一个愉快的夜晚。 感谢您的宝贵时间。
最佳答案
我将用不同的语言向您解释 Derick Bailey 在您引用的博文中已经说过的内容。
观看次数
您需要两个 View 才能完成这项工作。
第一个,“母 View ”,是包含递归结构作为其子节点的最外层 View 。这可以是 Marionette.CollectionView 或 Marionette.CompositeView。
第二个 View 是您的递归 View ,这意味着它需要是 Marionette.CompositeView。通过不指定“itemView”属性,您可以使 Marionette.CompositeView 递归。在缺少 itemView 属性的情况下,Marionette.CompositeView 将使用 ITSELF 来呈现给定集合的模型。
收藏
您需要一个集合,它可以是嵌套的 Backbone.Collection 的 Backbone.Collection,或者只是一个包含深度嵌套的哈希的 Backbone.Collection。在后一种情况下,在将简单哈希传递给 Marionette.CompositeView 时,您不需要忘记将它们转换为 Backbone.Collections(如下面在 RecursiveView 的 initialize() 方法中所做的那样)。
将它们放在一起
var RecursiveView = Marionette.CompositeView.extend({
template: '#someTemplate',
initialize: function () {
this.collection = this.model.get('children')
}
});
var MotherView = Marionette.CollectionView.extend({
itemView: RecursiveView,
collection: new Backbone.Collection([{key: 'value', children: [{}, {}, {}]}])
});
问题:事件冒泡
自然地,DOM 事件现在会冒泡,所以这段代码
var RecursiveView = Marionette.CompositeView.extend({
events: {
'click button': someCallback
}
});
将是它引用的 View 及其所有后代的事件的包罗万象。
解决此问题的最简单方法是使用直接后代 css 选择器 >
,例如
var RecursiveView = Marionette.CompositeView.extend({
events: {
'click >button': someCallback
}
});
如果这还不够,一个有效的解决方案是防止自动事件冒泡,例如
var RecursiveView = Marionette.CompositeView.extend({
events: {
'click button': function (event) {
event.stopPropagation();
// or event.stopImmediatePropagation() depending on your use case
// cf. http://stackoverflow.com/a/5299841/899586 and
}
}
});
关于javascript - 使用 CompositeView 呈现递归结构,同时使用 Marionette 将每个模型封装在 ItemView 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19238184/