Javascript 使用CompositeView呈现递归结构,同时使用木偶将每个模型封装在ItemView中
我将从一个明确的问题开始,然后解释:Javascript 使用CompositeView呈现递归结构,同时使用木偶将每个模型封装在ItemView中,javascript,backbone.js,recursion,marionette,Javascript,Backbone.js,Recursion,Marionette,我将从一个明确的问题开始,然后解释: 如何将包含在复合视图中的模型正确封装到项目视图中 我的问题很简单,但我不能设法让一些好的工作。 我有一本笔记簿。 每个便笺都是一个Backbone.model,并有一个@subjects集合, 然后,我有一个主干.Collection来表示该树(其中@substands是一个实例) 我设置了一个基本的集合视图,其中组合视图作为项目视图。一切都很完美,我很高兴。此工作解决方案显示在第一段代码中 问题来了。在此基础上,我遇到了这个问题: 这对我的事件在哪里有意义
如何将包含在
复合视图中的模型正确封装到项目视图中
我的问题很简单,但我不能设法让一些好的工作。
我有一本笔记簿。
每个便笺都是一个Backbone.model,并有一个@subjects
集合,
然后,我有一个主干.Collection来表示该树(其中@substands是一个实例)
我设置了一个基本的集合视图
,其中组合视图作为项目视图
。一切都很完美,我很高兴。此工作解决方案显示在第一段代码中
问题来了。在此基础上,我遇到了这个问题:
这对我的事件在哪里有意义。起初,我只是简单地添加了唯一的选择器(将数据guid添加到我的html元素中,这样我就可以通过它来获取它们),它工作正常,尽管它已经变得“粗糙”。但其他类似的问题也出现了,所以我决定需要一个解决方案。
因此,我告诉myslef,让我们将每个模型封装在ItemView中,并使用复合视图递归地呈现它们。
但是这并不是世界上最好的
以下是我一开始的情况:
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现在只是一个空模板)
UN
桌棋类游戏
{{{indent}}{{{title}}}
#这就是我放孩子们笔记的地方
所以这几乎是可行的。但是它很粗糙而且。。嗯,还是不太管用。我已经阅读了所有的文档,我已经阅读了这两个链接,但我仍然觉得我遗漏了一些重要的细节
作为一个答案,我在寻找的是任何提示或任何常用的方法来管理这个木偶。我真的在寻找一些干净的东西,因为这将是构建应用程序的一个角度部分。
也许我也找错地方了?什么都欢迎!!多谢各位
祝大家晚上过得愉快。
谢谢您的时间。我将用不同的语言向您解释德里克·贝利在您引用的博文中已经说过的话
视图
您需要两个视图才能完成此操作
第一个是“母视图”,它是最外层的视图,包含递归结构作为其子节点。这可以是木偶图.CollectionView或木偶图.CompositeView
第二个视图是递归视图,这意味着它需要是一个木偶。通过不指定“itemView”属性,可以使Marionette.CompositeView递归。在缺少itemView属性的情况下,Marionette.CompositeView将使用自身来呈现给定集合的模型
收藏
您需要一个集合,它可以是一个主干。嵌套主干。集合的集合,也可以是一个包含深度嵌套哈希的主干。集合。在后一种情况下,您不必忘记将简单哈希值转换为Backbone.Collections,然后将它们交给一个Marionette.CompositeView(如下在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
}
});
将是它引用的视图及其所有子体的事件的总括
解决此问题的最简单方法是使用直接后代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
}
}
});
工作演示-详细信息-感谢您链接问题中已有的链接!。。这个代码和我发布的第一个代码有什么区别?没有一个我有这个工作,非常感谢。我正在寻找一种方法来封装生成的html,这样最里面的视图只能访问它的html,而不能访问整个层次结构的html。好的,对不起,误读了你的文章,真的错了。为什么不添加直系子体选择器
,以便只检查直系子体上发生的DOM事件?如果这对您来说还不够的话,我宁愿攻击事件传播方面的问题:停止递归视图中的事件冒泡!因此,你提出的解决方案确实有效,它们实际上正是我目前所拥有的。问题是,我发现这个问题很棘手,我想在ItemView中清晰地封装所有内容。但是通过对代码的处理,我得出了这样的结论:这可能不太可能,因为这样做显然会丢失递归性。然后你会发现自己正在重新实现它。。你对那个方向有什么暗示吗?如果没有其他问题,我会记下你的答案,尽管它实际上对我没有帮助,但你确实花了时间!问题是,事件冒泡不是在backbone.view/marionete.view范围内发生的,而是纯粹在DOM本身内发生的。主干网/木偶网一侧没有发生您可以禁用的事件调度。这里冒泡的事件纯粹是DOM的一个“特性”。因此,您必须在DOM中构建一个平面层次结构,因为事件只会向其父级而不是其兄弟级冒泡。然后,您将需要适当的CSS或JS代码来创建视觉错觉,即所讨论的DOM元素实际上处于视觉层次结构中……:)因此,stopPropagation()是中断DOM标准功能的“黑客”。在代码中的其他地方,这确实可以被认为是骇客的、罪恶的,您可能期望事件会冒泡。因此,第一个解决方案是可怕的
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
}
}
});