Optimizing Slow CollectionViews
In Marionette.js re-rendering large lists while keeping performance high can be difficult.
Marionette abstracts a lot of the hard parts from you; however, there are still several anti-patterns that permeate apps, slowing render times down to a crawl.
Here are a few solutions to speed things up. They are not perfect for all applications, but they have worked well for me in the past.
Case #1: Minimize the work in onRender
itemView onRender jQuery calls when you have multiple rerenders of a collectionView
The client comes to you and asks, on hover of an item in this list, I should see a tooltip with the long title.
A simple task for
ItemViews—or at least it seems.
itemView as follows:
class Cat extends Marionette.ItemView # ... onRender: -> @$('[title]').tooltip()
This is going to give you exactly what you want. However, when your list is large, this is going to significantly slow down your render speed. Why? Because each of your
itemViews will execute this code within the
addItemView method on the
The solution is to pull this UI interaction behavior out of the
itemViews and into the
class CatList extends Marionette.CollectionView onRender: -> @$('[title]').tooltip()
Now the tooltip behavior runs once after all of your items have been rendered.
Case #2: filtering at an itemView level
React to model changes to toggle visibility within a collectionView, without rerendering the entire collection
Filtering is the bane of many developers. Perhaps in your UX when a user syncs with the persistence layer, single models in your collection will change one of their attributes which then will be represented in the UI by hiding the
itemView as follows
class Crayon extends Marionette.ItemView # ... modelEvents: -> change:color: @handleVisibility handleVisibility: -> if @model.get('color') is "red" then @$el.hide() else @$el.show()
This optimization is handy when you want your
collectionView to be a bit dumb and want to let the
itemViews determine their own visibility status in the UI.
Case #3: filtering at a collectionView level
Handle view visibility during collectionView rendering, without having to render your entire collection
When you have a large collection and want to display a subset of that list, there are several solutions. You can create a new collection containing the models, or use a backbone plugin to give your collection filter behaviors.
Here is an approach that I use from within the
class People extends Marionette.CollectionView addItemView: (item) -> super if item.shouldBeShown()
This works well because all models hit
addItemView before they are rendered; thus you can short-circuit the entire render logic if the model does not pass your render conditions.
Hopefully this helps you on your way to building more performant web applications!
Sam Saccone - @samccone