From 63a0582fa3d0ea75e4b90ef943eedf336aa73c6e Mon Sep 17 00:00:00 2001 From: John Cowen Date: Thu, 20 Jun 2019 09:38:23 +0100 Subject: [PATCH] ui: Reduce mutation of html.classList (#5974) Throughout the app we mutate the value of the root node classList on navigation between separate pages (basically on URL change). Every template has a unique classList for example `template-service template-show` and `template-service template-list` etc etc. When navigating between 2 pages, both pages using the same template yet with different data, previoulsy we would entirely clear out the `html.classList` and then refill it again with eaxctly the same classes. This commit moves this to perform a diff previous to mutating the classList, and then potentially no classList mutating is needed when moving between 2 pages of the same template. --- ui-v2/app/components/app-view.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui-v2/app/components/app-view.js b/ui-v2/app/components/app-view.js index ed526eab0d..f4ae4791ce 100644 --- a/ui-v2/app/components/app-view.js +++ b/ui-v2/app/components/app-view.js @@ -11,6 +11,7 @@ export default Component.extend(SlotsMixin, { classNameBindings: ['enabled::disabled', 'authorized::unauthorized'], dom: service('dom'), didReceiveAttrs: function() { + this._super(...arguments); // right now only manually added classes are hoisted to const $root = get(this, 'dom').root(); let cls = get(this, 'class') || ''; @@ -22,18 +23,22 @@ export default Component.extend(SlotsMixin, { if (cls) { // its possible for 'layout' templates to change after insert // check for these specific layouts and clear them out - [...$root.classList].forEach(function(item, i) { + const receivedClasses = new Set(templatize(cls.split(' '))); + const difference = new Set([...$root.classList].filter(item => !receivedClasses.has(item))); + [...difference].forEach(function(item, i) { if (templatize(['edit', 'show', 'list']).indexOf(item) !== -1) { $root.classList.remove(item); } }); - $root.classList.add(...templatize(cls.split(' '))); + $root.classList.add(...receivedClasses); } }, didInsertElement: function() { + this._super(...arguments); this.didReceiveAttrs(); }, didDestroyElement: function() { + this._super(...arguments); const cls = get(this, 'class') + ' loading'; if (cls) { const $root = get(this, 'dom').root();