我将从一个明确的问题开始,然后解释:
如何将包含在 CompositeView
中的模型正确封装到 ItemView
我的问题很简单,但我无法设法得到一些好的工作。
我有一棵笔记树。
每个音符都是一个 Backbone.model 并且有一个 @descendants
集合,
然后我有一个 Backbone.Collection 来代表那棵树(其中@descendants 是一个实例)
我设置了一个基本的 CollectionView
,作为 itemView
, CompositeView
。一切都完美呈现,我对此感到非常高兴。这个有效的解决方案显示在第一个代码片段中!
问题来了。在此基础上,我有点遇到了这个问题:Events fired for whole hierarchy
这对于我的事件如何绑定(bind)是有意义的。起初,我只是添加了唯一的选择器(向我的 html 元素添加了 data-guid,以便我可以通过它来获取它们)并且它工作正常,尽管它已经变得“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
所以这几乎是有效的。但它是hacky 并且.. 好吧,它仍然不能正常工作。我一直在阅读所有文档,并且我已经阅读了 Derick Bailey on nested structure and CompositeView 和 David Sulc on Nested Views 这两个链接,但我仍然觉得我遗漏了一些重要的细节。作为答案,我正在寻找的是任何提示或使用 Marionette 管理此问题的任何常用方法。我真的在寻找干净的东西,因为这将成为构建应用程序的 Angular 部分之一。
也许我也在错误的地方搜索?任何东西都会受欢迎!!非常感谢你
祝大家度过一个愉快的夜晚。
感谢您的时间。
最佳答案
我将用不同的语言向您解释 Derick Bailey 在您引用的博客文章中已经说过的内容。
View
您需要两个 View 来完成这项工作。
第一个,“母 View ”,是包含递归结构作为其子节点的最外层 View 。这可能是 Marionette.CollectionView 或 Marionette.CompositeView。
第二个 View 是您的递归 View ,这意味着它必须是 Marionette.CompositeView。通过不指定“itemView”属性,您可以使 Marionette.CompositeView 递归。由于缺少 itemView 属性,Marionette.CompositeView 将使用 ITSELF 来呈现给定的集合的模型。
收藏
您需要一个集合,它要么是嵌套 Backbone.Collections 的 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/