|
1 |
| -# Upgrade Guide from v2 to v3 |
| 1 | +# Upgrade Guide |
2 | 2 |
|
3 | 3 | Marionette 3 introduces a number of breaking changes. This upgrade guide will go
|
4 | 4 | through the major changes and describe how to change your application to
|
5 | 5 | accommodate them.
|
6 | 6 |
|
7 |
| -## Required changes |
8 |
| -These are breaking changes that need to be handled when migrating from Marionette v2 to v3 |
| 7 | +An [upgrade tool](https://github.com/marionettejs/marionette-v3-compat) is available |
| 8 | +and covers the breaking changes in detail. |
9 | 9 |
|
10 |
| -#### LayoutView has been removed |
| 10 | +Where possible, we will document how to make the changes in Marionette 2.x so |
| 11 | +that your applications can continue to work and to ease the burden of upgrading |
| 12 | +to Marionette 3. |
11 | 13 |
|
12 |
| - * **Old behavior:** `LayoutView` implemented the features to manage subregions |
13 |
| - * **New behavior:** The `LayoutView` functionality was merged into `View` class |
14 |
| - * **Reason:** API simplification |
15 |
| - * **Remedy:** Rename `LayoutView` to `View` |
16 |
| - |
17 |
| -#### ItemView has been renamed to View |
| 14 | +You can run Marionette 3 alongside Marionette 2 with the Marionette.noConflict() function. |
18 | 15 |
|
19 |
| - * **Old behavior:** `ItemView` was the recommended class to render a single view |
20 |
| - * **New behavior:** The `View` is recommended class to render a single view or a view |
21 |
| - with subregions |
22 |
| - * **Reason:** API simplification |
23 |
| - * **Remedy:** Rename `ItemView` to `View` |
| 16 | +## Views |
24 | 17 |
|
25 |
| -#### CollectionView.getEmptyView has been removed |
| 18 | +The most noticeable change to Marionette 3 is the consolidation of `ItemView` |
| 19 | +and `LayoutView` into `View`. In addition, `CompositeView` has been removed and |
| 20 | +its functionality merged into `CollectionView` and `View`. |
26 | 21 |
|
27 |
| - * **Old behavior:** `CollectionView.getEmptyView` was provided |
28 |
| - * **New behavior:** There's no `CollectionView.getEmptyView` |
29 |
| - * **Reason:** API simplification |
30 |
| - * **Remedy:** Rename `getEmptyView` to `emptyView` |
| 22 | +### Removing `LayoutView` and `ItemView` |
31 | 23 |
|
32 |
| -#### CollectionView.getChildView has been removed |
| 24 | +Using separate `View` `LayoutView` and `ItemView` was complicating the API for |
| 25 | +Marionette needlessly. The new `View` replaces all of this and sets a clear |
| 26 | +recommendation for building layout trees. |
33 | 27 |
|
34 |
| - * **Old behavior:** `CollectionView.getChildView` was provided |
35 |
| - * **New behavior:** There's no `CollectionView.getChildView` |
36 |
| - * **Reason:** API simplification |
37 |
| - * **Remedy:** Rename `getChildView` to `childView` |
38 |
| - * |
| 28 | +#### Upgrading for Marionette 2.x |
39 | 29 |
|
40 |
| -## Recommended changes (deprecations) |
41 |
| -These changes are optional, although recommended to make future upgrades easy |
| 30 | +For updating in Marionette 2.x, it is recommended you change all instances of |
| 31 | +`ItemView` to `LayoutView`. |
42 | 32 |
|
43 |
| -#### CompositeView is deprecated |
| 33 | +#### Upgrading to Marionette 3 |
44 | 34 |
|
45 |
| - * **Old behavior:** `CompositeView` was fully supported |
46 |
| - * **New behavior:** The `CompositeView` is deprecated |
47 |
| - * **Reason:** API simplification |
48 |
| - * **Remedy:** Use `CollectionView` or `NextCollectionView` instead |
| 35 | +Change all instances of `LayoutView` and `ItemView` to `View`. Any views that |
| 36 | +previously extended `View` with a custom `render` should work relatively |
| 37 | +unchanged. |
| 38 | + |
| 39 | +### Removing `CompositeView` |
| 40 | + |
| 41 | +The `CompositeView` was deprecated in favor of using `View` and |
| 42 | +`CollectionView`. The `CompositeView` will be completely removed in Marionette |
| 43 | +4. |
| 44 | + |
| 45 | +See [`CollectionView`](./marionette.collectionview.md#rendering-collectionviews) |
| 46 | +for detail on upgrading to Marionette 3. This technique works in both Marionette |
| 47 | +2.x and Marionette 3. |
| 48 | + |
| 49 | +### Removing `CollectionView.getChildView()` |
| 50 | + |
| 51 | +The `getChildView` method has been removed in favor of the `childView` property, |
| 52 | +[which now accepts a function](basics.md#functions-returning-values). |
| 53 | + |
| 54 | +#### Upgrading to Marionette 3 |
| 55 | + |
| 56 | +Simply replace all instances of `getChildView` with `childView`. |
| 57 | + |
| 58 | +### Removing `CollectionView.getEmptyView()` |
| 59 | + |
| 60 | +The `getEmptyView` method has been removed in favor of the `emptyView` property, |
| 61 | +[which now accepts a function](basics.md#functions-returning-values). |
| 62 | + |
| 63 | +#### Upgrading to Marionette 3 |
| 64 | + |
| 65 | +Simply replace all instances of `getEmptyView` with `emptyView`. |
| 66 | + |
| 67 | +### Child event handlers |
| 68 | + |
| 69 | +The `childEvents` attribute was renamed to `childViewEvents`. |
| 70 | + |
| 71 | +Child event bubbling above one level is now removed in most instances and |
| 72 | +deprecated pending removal everywhere else. This can no longer be relied upon. |
| 73 | +To pass events further up the chain, you must explicitly using |
| 74 | +`childViewTriggers` to convert the event from the child into an event on the |
| 75 | +parent. These can be chained all the way up to the level you require them to be. |
| 76 | + |
| 77 | +Bubbled child events no longer pass the `childView` implicitly and only pass the |
| 78 | +arguments passed as part of `triggerMethod`. This means that the arguments |
| 79 | +passed to `onEvent` and `onChildviewEvent` are now identical. See the |
| 80 | +[documentation on event lifecycles](./view.lifecycle.md) for more information. |
| 81 | + |
| 82 | +In Marionette 2, `childEvents` were bound on every event. In Marionette 3, |
| 83 | +`childViewEvents` are bound once and cached. This means that you cannot add new |
| 84 | +events after the view has been created. |
| 85 | + |
| 86 | +### View `triggers` |
| 87 | + |
| 88 | +The view `triggers` attribute no longer passes an `options` attribute to event |
| 89 | +handlers, instead passing the view instance that triggered the event. |
| 90 | + |
| 91 | +## Events |
| 92 | + |
| 93 | +A number of lifecycle events were changed or removed from Marionette 3. |
| 94 | +Information on which ones were removed, changed, or added will be found here |
| 95 | +with recommendations on how to update your code. |
| 96 | + |
| 97 | +### `show` and `before:show` |
| 98 | + |
| 99 | +The `show` events were removed completely as they were redundant and were being |
| 100 | +used incorrectly to show child regions. The `show` event was fired after the |
| 101 | +view had been attached, meaning the DOM was being constantly updated, leading to |
| 102 | +deteriorated performance. |
| 103 | + |
| 104 | +#### Upgrading for Marionette 2.x |
| 105 | + |
| 106 | +Replace all instances of `onShow`, `on('show')`, `onBeforeShow` and |
| 107 | +`on('before:show')` to use the `render` and `before:render` events. This is the |
| 108 | +recommendation for Marionette 3 and ensures the DOM tree is built in-memory |
| 109 | +before modifying the DOM. |
| 110 | + |
| 111 | +#### Upgrading to Marionette 3 |
| 112 | + |
| 113 | +Replace all instances of `show` and `before:show` with `render` and |
| 114 | +`before:render`. If you want the view to be visible in the DOM, then listen to |
| 115 | +the `dom:refresh` event. |
| 116 | + |
| 117 | +### Changes to `region.show()` |
| 118 | + |
| 119 | +The `region.show()` method (that also backs `showChildView()`) was changed to |
| 120 | +not remove HTML outside the `$el` of the displayed view. In Marionette 2, |
| 121 | +the `region.show()` method would call `region.$el.empty()` before showing the |
| 122 | +new HTML. |
| 123 | + |
| 124 | +In Marionette 3, this was changed to unhook `region.currentView` from the DOM, |
| 125 | +remove all event handlers, then delete it. Any HTML added to the region that |
| 126 | +isn't contained in the DOM of the View won't be removed. |
| 127 | + |
| 128 | +For example: |
| 129 | + |
| 130 | +```javascript |
| 131 | +var _ = require('underscore'); |
| 132 | +var Mn = require('backbone.marionette'); |
| 133 | + |
| 134 | +var app = require('./app'); |
| 135 | + |
| 136 | +var MyView = Mn.View.extend({ |
| 137 | + template: _.template('View contents') |
| 138 | +}); |
| 139 | + |
| 140 | +var ParentView = Mn.View.extend({ |
| 141 | + template: _.template('<div class="view-hook"></div>'), |
| 142 | + regions: { |
| 143 | + child: '.view-hook' |
| 144 | + } |
| 145 | +}); |
| 146 | + |
| 147 | +var parent = new ParentView(); |
| 148 | +app.showView(parent); |
| 149 | + |
| 150 | +var child = new MyView(); |
| 151 | + |
| 152 | +parent.showChildView('child', child); |
| 153 | +parent.getRegion('child').$el.append('<p>Not removed</p>'); |
| 154 | +parent.showChildView('child', new MyView()); |
| 155 | +``` |
| 156 | + |
| 157 | +In Marionette 2, the HTML output will be: |
| 158 | + |
| 159 | +```html |
| 160 | +<div class="view-hook"> |
| 161 | + <div>View contents</div> |
| 162 | +</div> |
| 163 | +``` |
| 164 | + |
| 165 | +In Marionette 3, the HTML will be: |
| 166 | + |
| 167 | +```html |
| 168 | +<div class="view-hook"> |
| 169 | + <p>Not Removed</p> |
| 170 | + <div>View contents</div> |
| 171 | +</div> |
| 172 | +``` |
| 173 | + |
| 174 | +### Arguments for Lifecycle Events |
| 175 | + |
| 176 | +The arguments for a number of lifecycle events were changed. For consistency, |
| 177 | +all events will now receive the view that is emitting the event as the first |
| 178 | +argument. See the [documentation for view lifecycles](./view.lifecycle.md) for |
| 179 | +more complete information. |
| 180 | + |
| 181 | +#### Upgrading to Marionette 3 |
| 182 | + |
| 183 | +The following events, with their accompanying `before:` event were changed and |
| 184 | +may need to be updated: |
| 185 | + |
| 186 | +| Class | Event | |
| 187 | +|------------------|----------------------------------| |
| 188 | +| `Object` | `destroy` | |
| 189 | +| `Region` | `show` | |
| 190 | +| `View` | `add:region` and `remove:region` | |
| 191 | +| `CollectionView` | `add:child` and `remove:child` | |
| 192 | +| `Application` | `start` | |
| 193 | + |
| 194 | +## Templates |
| 195 | + |
| 196 | +The biggest change to templates is renaming `templateHelpers` to |
| 197 | +`templateContext` - the aim is to be more in-line with terminology from other |
| 198 | +frameworks. |
| 199 | + |
| 200 | +### Upgrading to Marionette 3 |
| 201 | + |
| 202 | +Simply replace all instances of `templateHelpers` with `templateContext` |
| 203 | + |
| 204 | +## Regions |
| 205 | + |
| 206 | +There are a number of changes to how regions behave - the biggest change being |
| 207 | +the removal of the ability to access regions as attributes |
| 208 | + |
| 209 | +### Removing `view.region` |
| 210 | + |
| 211 | +The `view.<region_name>` syntax has been removed in favor of `view.getRegion()`, |
| 212 | +`view.getChildView()` and `view.showChildView()`. |
| 213 | + |
| 214 | +#### Upgrading for Marionette 2.x |
| 215 | + |
| 216 | +Change all references to `view.region` to `view.getRegion('region')`. For |
| 217 | +example, in Mn 2.x and below: |
| 218 | + |
| 219 | +```javascript |
| 220 | +var AnotherView = require('./anotherview'); |
| 221 | + |
| 222 | +var MyView = Mn.LayoutView.extend({ |
| 223 | + regions: { |
| 224 | + myregion: '.regionname' |
| 225 | + }, |
| 226 | + |
| 227 | + onRender: function() { |
| 228 | + this.myregion.show(new AnotherView()); |
| 229 | + } |
| 230 | +}); |
| 231 | +``` |
| 232 | + |
| 233 | +This does not work in Mn 3 - instead do: |
| 234 | + |
| 235 | +```javascript |
| 236 | +var AnotherView = require('./anotherview'); |
| 237 | + |
| 238 | +/* In Mn 2.x we can just use LayoutView */ |
| 239 | +var MyView = Mn.View.extend({ |
| 240 | + regions: { |
| 241 | + myregion: '.regionname' |
| 242 | + }, |
| 243 | + |
| 244 | + onRender: function() { |
| 245 | + this.showChildView('myregion', new AnotherView()); |
| 246 | + } |
| 247 | +}); |
| 248 | +``` |
| 249 | + |
| 250 | +See the documentation for [views](marionette.view.md#laying-out-views---regions) |
| 251 | +to learn more about how to manage regions in Marionette 3. |
| 252 | + |
| 253 | +## Modules |
| 254 | + |
| 255 | +Marionette Modules have been completely removed in favor of using the more |
| 256 | +standard JavaScript module loaders e.g. |
| 257 | +[Webpack](./installation.md#quick-start-using-npm-and-webpack) or |
| 258 | +[Browserify](./installation.md#quick-start-using-npm-and-browserify). See the |
| 259 | +[installation](./installation.md) documentation for a list of potential options. |
| 260 | + |
| 261 | +## Backbone.Babysitter |
| 262 | + |
| 263 | +The dependency on `Backbone.Babysitter` has been removed in favour of an |
| 264 | +in-built implementation that is maintained within the main Marionette codebase. |
| 265 | + |
| 266 | +BabySitter provides a simple way to manage child views in Backbone/Marionette or |
| 267 | +any object that manages lists of views. The external Babysitter library was used |
| 268 | +in Marionette to manage the `CollectionView` children. |
| 269 | + |
| 270 | +### Main Differences |
| 271 | + |
| 272 | +The main difference between Babysitter and the Marionette implementation is the |
| 273 | +removal of `.call` and `.apply` on `CollectionView.children`. Instead you should |
| 274 | +use `.invoke` or |
| 275 | +[any of the methods provided](./marionette.collectionview.md#collectionview-childview-iterators-and-collection-functions). |
| 276 | + |
| 277 | +For example: |
| 278 | + |
| 279 | +```javascript |
| 280 | +var MyCollectionView = require('./views'); |
| 281 | +var MyCollection = require('./collections'); |
| 282 | + |
| 283 | +var collection = new MyCollection(); |
| 284 | +collection.fetch(); |
| 285 | + |
| 286 | +var myView = new MyCollectionView({collection: collection}); |
| 287 | +myView.children.invoke('render'); |
| 288 | +myView.children.map(function(view) { |
| 289 | + view.doMethod(); |
| 290 | +}); |
| 291 | +``` |
0 commit comments