ツリー構造をレンダリングする多くの CompositeViews をインスタンス化する CollectionView を使用して、Backbone.Marionette 上にアプリケーションを構築しています。
Zombie Views ( Bailey on Zombies ) と、View および Region のドキュメントを読みました。ただし、読み取り時にすべてが非常に単純に見える場合、実行はまったく別の問題です。
ルートのいずれかにヒットすると、キーボード ショートカットが複数回起動されてしまいます。回避策を見つけましたが、この回避策は、ビューの変更をレンダリングする際に別の問題を引き起こします。
キーボード ショートカットを複数回トリガーする実際のコードを次に示します。ではSnippet A
、通常、ビューを閉じるには、App.contentRegion.currentView.treeRegion.close()
showContentView: (tree) ->
if @treeView?
App.contentRegion.currentView.treeRegion.reset()
App.contentRegion.currentView.treeRegion.close()
@treeView.close()
delete @treeView
@treeView = new App.Note.TreeView(collection: tree)
App.contentRegion.currentView.treeRegion.show @treeView
Snippet B
以下の、キーボード ショートカットの問題を修正します。ただし、追加で作成されたモデル (CompositeView) がユーザーにレンダリングされないという問題が発生します。
showContentView: (tree) ->
if @treeView?
@treeView.collection = tree
@treeView.render()
else
@treeView = new App.Note.TreeView(collection: tree)
App.contentRegion.currentView.treeRegion.show @treeView
ここで CollectionView を初期化し、次に CompositeViews をレンダリングします。
initialize: -> # collectionView
@listenTo @collection, "sort", @render
@listenTo @collection, "destroy", @addDefaultNote
Note.eventManager.on 'createNote', @createNote, this
Note.eventManager.on 'change', @dispatchFunction, this
@drag = undefined
initialize: -> # compositeView
@collection = @model.descendants
@bindKeyboardShortcuts()
@listenTo @collection, "sort", @render
Note.eventManager.on "setCursor:#{@model.get('guid')}", @setCursor, @
Note.eventManager.on "render:#{@model.get('guid')}", @render, @
Note.eventManager.on "setTitle:#{@model.get('guid')}", @setNoteTitle, @
これは、CompositeViews でキーボード ショートカットをバインドする方法です。
bindKeyboardShortcuts: ->
@.$el.on 'keydown', null, 'ctrl+shift+backspace', @triggerShortcut 'deleteNote'
@.$el.on 'keydown', null, 'tab', @triggerShortcut 'tabNote'
@.$el.on 'keydown', null, 'shift+tab', @triggerShortcut 'unTabNote'
@.$el.on 'keydown', null, 'alt+right', @triggerShortcut 'tabNote'
@.$el.on 'keydown', null, 'alt+left', @triggerShortcut 'unTabNote'
@.$el.on 'keydown', null, 'alt+up', @triggerShortcut 'jumpPositionUp'
@.$el.on 'keydown', null, 'alt+down', @triggerShortcut 'jumpPositionDown'
@.$el.on 'keydown', null, 'up', @triggerShortcut 'jumpFocusUp'
@.$el.on 'keydown', null, 'down', @triggerShortcut 'jumpFocusDown'
@.$el.on 'keydown', null, 'alt+ctrl+left', @triggerShortcut 'zoomOut'
@.$el.on 'keydown', null, 'alt+ctrl+right', @triggerShortcut 'zoomIn'
そして、私がそれらをトリガーする方法
triggerShortcut: (event) -> (e) =>
e.preventDefault()
e.stopPropagation()
@triggerEvent(event).apply(@, Note.sliceArgs arguments)
triggerEvent: (event) ->
(e) =>
@updateNote()
args = ['change', event, @model].concat(Note.sliceArgs arguments, 0)
Note.eventManager.trigger.apply(Note.eventManager, args)
最後に、すべてがクリーンであることを確認するために、onBeforeClose ですべてのショートカットのバインドを解除します。また、eventManager のリスナーのバインドを解除します。
onBeforeClose: ->
console.log "view being closed", @
@$el.off()
Note.eventManager.off "setCursor:#{@model.get('guid')}"
Note.eventManager.off "render:#{@model.get('guid')}"
Note.eventManager.off "setTitle:#{@model.get('guid')}"
Note.eventManager.off "timeoutUpdate:#{@model.get('guid')}"
問題の原因は@treeView = new App.Note.TreeView(collection: tree)
. それぞれ(スニペット A) に新しいTreeViewを作成すると、追加されたすべてのモデルがビューに適切にレンダリングされますが、ショートカットが狂ってしまいます。
一方、1 つの TreeView を作成してそのコレクション (スニペット B) を交換すると、ビューでレンダリングの問題が発生しますが、ショートカットは問題ありません! @showContentView
必要なものはすべて含めようとしましたが、それ以上のものはありません (すでにかなりのコードです..) が、他に何か必要な場合はお問い合わせください!
私はそれを十分に理解できることを願っています..
[編集] ショートカットのバグを取り除くためにさまざまな組み合わせを試しましたが、showContentView ごとに新しい TreeView を作成すると、ビューが正しく閉じられないようです。これは、より深いメモリリークの問題に起因していると思います。その点に関しては、おそらく別の StackOverflow の質問を作成し、追加情報についてはこの質問にリンクします。
どうもありがとうございました!