From a5c6d5f074e4614fe64fa377d2f8d220d8472de9 Mon Sep 17 00:00:00 2001 From: Dan Popescu Date: Tue, 29 Mar 2022 16:31:51 +0300 Subject: [PATCH] fix(cache): avoid stack overflow because of vue reusing elements --- ui/src/components/btn-dropdown/QBtnDropdown.js | 3 +++ ui/src/components/carousel/QCarousel.js | 6 +++--- ui/src/components/chip/QChip.js | 2 ++ ui/src/components/color/QColor.js | 15 +++++++++++++++ ui/src/components/date/QDate.js | 14 ++++++++++++-- .../components/dialog-bottom-sheet/BottomSheet.js | 1 + ui/src/components/dialog-plugin/DialogPlugin.js | 5 +++++ .../components/expansion-item/QExpansionItem.js | 2 ++ ui/src/components/fab/QFab.js | 1 + ui/src/components/file/QFile.js | 4 +++- ui/src/components/footer/QFooter.js | 1 + ui/src/components/header/QHeader.js | 1 + ui/src/components/knob/QKnob.js | 1 + ui/src/components/layout/QLayout.js | 3 +++ ui/src/components/option-group/QOptionGroup.js | 1 + ui/src/components/pagination/QPagination.js | 2 ++ ui/src/components/popup-edit/QPopupEdit.js | 3 +++ ui/src/components/radio/QRadio.js | 1 + ui/src/components/rating/QRating.js | 2 +- .../components/resize-observer/QResizeObserver.js | 1 + ui/src/components/scroll-area/QScrollArea.js | 6 ++++++ .../slide-transition/QSlideTransition.js | 1 + ui/src/components/splitter/QSplitter.js | 2 ++ ui/src/components/stepper/QStepper.js | 1 + ui/src/components/stepper/StepHeader.js | 1 + ui/src/components/table/QTable.js | 1 + ui/src/components/table/table-bottom.js | 1 + ui/src/components/table/table-header.js | 1 + ui/src/components/tabs/QTabs.js | 4 ++++ ui/src/components/time/QTime.js | 7 +++++++ ui/src/components/tree/QTree.js | 1 + ui/src/components/uploader/QUploaderBase.js | 2 ++ ui/src/mixins/checkbox.js | 1 + ui/src/mixins/file.js | 1 + ui/src/mixins/panel.js | 1 + ui/src/plugins/Loading.js | 1 + 36 files changed, 94 insertions(+), 7 deletions(-) diff --git a/ui/src/components/btn-dropdown/QBtnDropdown.js b/ui/src/components/btn-dropdown/QBtnDropdown.js index 65fbed782922..e13432b18244 100644 --- a/ui/src/components/btn-dropdown/QBtnDropdown.js +++ b/ui/src/components/btn-dropdown/QBtnDropdown.js @@ -106,6 +106,7 @@ export default Vue.extend({ this.disableDropdown !== true && Arrow.push( h(QMenu, { + key: 'menu', ref: 'menu', attrs: { id: this.targetUid @@ -148,6 +149,7 @@ export default Vue.extend({ if (this.split === false) { return h(QBtn, { + key: 'nonSpl', class: 'q-btn-dropdown q-btn-dropdown--simple', props: { ...this.$props, @@ -171,6 +173,7 @@ export default Vue.extend({ } const Btn = h(QBtn, { + key: 'spl', class: 'q-btn-dropdown--current', props: { ...this.$props, diff --git a/ui/src/components/carousel/QCarousel.js b/ui/src/components/carousel/QCarousel.js index e4a889bebfd6..e56f86849cbb 100644 --- a/ui/src/components/carousel/QCarousel.js +++ b/ui/src/components/carousel/QCarousel.js @@ -156,7 +156,7 @@ export default Vue.extend({ const fn = this.$scopedSlots['navigation-icon'] !== void 0 ? this.$scopedSlots['navigation-icon'] : opts => h(QBtn, { - key: 'nav' + opts.name, + key: 'nav#' + opts.name, class: `q-carousel__navigation-icon q-carousel__navigation-icon--${opts.active === true ? '' : 'in'}active`, props: opts.btnProps, on: cache(this, 'nav#' + opts.name, { click: opts.onClick }) @@ -206,10 +206,10 @@ export default Vue.extend({ if (this.infinite === true || this.panelIndex > 0) { node.push( h('div', { - key: 'prev', staticClass: `q-carousel__control q-carousel__arrow q-carousel__prev-arrow q-carousel__prev-arrow--${this.direction} absolute flex flex-center` }, [ h(QBtn, { + key: 'prev', props: { icon: this.arrowIcons[0], ...this.controlProps }, on: cache(this, 'prev', { click: this.previous }) }) @@ -220,10 +220,10 @@ export default Vue.extend({ if (this.infinite === true || this.panelIndex < this.panels.length - 1) { node.push( h('div', { - key: 'next', staticClass: `q-carousel__control q-carousel__arrow q-carousel__next-arrow q-carousel__next-arrow--${this.direction} absolute flex flex-center` }, [ h(QBtn, { + key: 'next', props: { icon: this.arrowIcons[1], ...this.controlProps }, on: cache(this, 'next', { click: this.next }) }) diff --git a/ui/src/components/chip/QChip.js b/ui/src/components/chip/QChip.js index b90809e4adb2..f41c65001420 100644 --- a/ui/src/components/chip/QChip.js +++ b/ui/src/components/chip/QChip.js @@ -173,6 +173,7 @@ export default Vue.extend({ this.removable === true && child.push( h(QIcon, { + key: 'non', staticClass: 'q-chip__icon q-chip__icon--remove cursor-pointer', props: { name: this.removeIcon }, attrs: this.attrs.remove, @@ -197,6 +198,7 @@ export default Vue.extend({ } this.isClickable === true && Object.assign(data, { + key: 'click', attrs: this.attrs.chip, on: cache(this, 'click', { click: this.__onClick, diff --git a/ui/src/components/color/QColor.js b/ui/src/components/color/QColor.js index 7c5b7c01928b..e10a33f6d490 100644 --- a/ui/src/components/color/QColor.js +++ b/ui/src/components/color/QColor.js @@ -236,6 +236,7 @@ export default Vue.extend({ this.noHeaderTabs !== true && child.push( h(QTabs, { + key: 'topVTab', class: 'q-color-picker__header-tabs', props: { value: this.topView, @@ -269,6 +270,7 @@ export default Vue.extend({ staticClass: 'q-color-picker__header-banner row flex-center no-wrap' }, [ h('input', { + key: 'topIn', staticClass: 'fit', domProps: { value: this.model[this.topView] }, attrs: this.editable !== true ? { @@ -336,6 +338,7 @@ export default Vue.extend({ staticClass: 'q-color-picker__footer relative-position overflow-hidden' }, [ h(QTabs, { + key: 'ftIn', staticClass: 'absolute-full', props: { value: this.view, @@ -376,6 +379,7 @@ export default Vue.extend({ __getSpectrumTab (h) { return [ h('div', { + key: 'spectrT', ref: 'spectrum', staticClass: 'q-color-picker__spectrum non-selectable relative-position cursor-pointer', style: this.spectrumStyle, @@ -413,6 +417,7 @@ export default Vue.extend({ staticClass: 'q-color-picker__sliders' }, [ h(QSlider, { + key: 'hueSlide', staticClass: 'q-color-picker__hue non-selectable', props: { value: this.model.h, @@ -432,6 +437,7 @@ export default Vue.extend({ this.hasAlpha === true ? h(QSlider, { + key: 'alphaSlide', staticClass: 'q-color-picker__alpha non-selectable', props: { value: this.model.a, @@ -467,6 +473,7 @@ export default Vue.extend({ h('div', { staticClass: 'row items-center no-wrap' }, [ h('div', ['R']), h(QSlider, { + key: 'rSlide', props: { value: this.model.r, min: 0, @@ -481,6 +488,7 @@ export default Vue.extend({ }) }), h('input', { + key: 'rIn', domProps: { value: this.model.r }, attrs, on: cache(this, 'rIn', { @@ -494,6 +502,7 @@ export default Vue.extend({ h('div', { staticClass: 'row items-center no-wrap' }, [ h('div', ['G']), h(QSlider, { + key: 'gSlide', props: { value: this.model.g, min: 0, @@ -508,6 +517,7 @@ export default Vue.extend({ }) }), h('input', { + key: 'gIn', domProps: { value: this.model.g }, attrs, on: cache(this, 'gIn', { @@ -521,6 +531,7 @@ export default Vue.extend({ h('div', { staticClass: 'row items-center no-wrap' }, [ h('div', ['B']), h(QSlider, { + key: 'bSlide', props: { value: this.model.b, min: 0, @@ -535,6 +546,7 @@ export default Vue.extend({ }) }), h('input', { + key: 'bIn', domProps: { value: this.model.b }, attrs, on: cache(this, 'bIn', { @@ -548,6 +560,7 @@ export default Vue.extend({ this.hasAlpha === true ? h('div', { staticClass: 'row items-center no-wrap' }, [ h('div', ['A']), h(QSlider, { + key: 'aSlide', props: { value: this.model.a, color: 'grey', @@ -560,6 +573,7 @@ export default Vue.extend({ }) }), h('input', { + key: 'aIn', domProps: { value: this.model.a }, attrs, on: cache(this, 'aIn', { @@ -580,6 +594,7 @@ export default Vue.extend({ ? 'q-color-picker__palette-rows--editable' : '' }, this.computedPalette.map(color => h('div', { + key: 'palette#' + color, staticClass: 'q-color-picker__cube col-auto', style: { backgroundColor: color }, on: this.editable === true ? cache(this, 'palette#' + color, { diff --git a/ui/src/components/date/QDate.js b/ui/src/components/date/QDate.js index decf9437f2f9..4e13a3fad8cd 100644 --- a/ui/src/components/date/QDate.js +++ b/ui/src/components/date/QDate.js @@ -863,6 +863,7 @@ export default Vue.extend({ ]), this.todayBtn === true ? h(QBtn, { + key: 'today', staticClass: 'q-date__header-today self-start', props: { icon: this.$q.iconSet.datetime.today, @@ -883,6 +884,7 @@ export default Vue.extend({ staticClass: 'row items-center q-date__arrow' }, [ h(QBtn, { + key: 'go-#' + view, props: { round: true, dense: true, @@ -906,6 +908,7 @@ export default Vue.extend({ }, [ h('div', { key }, [ h(QBtn, { + key: 'view#' + view, props: { flat: true, dense: true, @@ -923,6 +926,7 @@ export default Vue.extend({ staticClass: 'row items-center q-date__arrow' }, [ h(QBtn, { + key: 'go+#' + view, props: { round: true, dense: true, @@ -983,6 +987,7 @@ export default Vue.extend({ }, this.daysOfWeek.map(day => h('div', { staticClass: 'q-date__calendar-item' }, [ h('div', [ day ]) ]))), h('div', { + key: 'kNavC', staticClass: 'q-date__calendar-days-container relative-position overflow-hidden', directives: cache(this, 'kNavC', [{ name: 'key-group-navigation', @@ -1000,6 +1005,7 @@ export default Vue.extend({ }, this.days.map(day => h('div', { staticClass: day.classes }, [ day.in === true ? h(QBtn, { + key: calCachePrefix + day.i, staticClass: day.today === true ? 'q-date__today' : null, ref: viewTarget === day.i ? 'viewTarget' : void 0, props: { @@ -1045,6 +1051,7 @@ export default Vue.extend({ staticClass: 'q-date__months-item flex flex-center' }, [ h(QBtn, { + key: 'month#' + i, staticClass: currentYear === true && this.today.month === i + 1 ? 'q-date__today' : null, ref: this.viewModel.month === i + 1 ? 'viewTarget' : void 0, props: Object.assign( @@ -1077,7 +1084,7 @@ export default Vue.extend({ ) return h('div', { - key: 'months-view', + key: 'kNavYM', staticClass: 'q-date__view q-date__months flex flex-center', directives: cache(this, 'kNavYM', [{ name: 'key-group-navigation', @@ -1114,7 +1121,7 @@ export default Vue.extend({ staticClass: 'q-date__years-item flex flex-center' }, [ h(QBtn, { - key: 'yr' + i, + key: 'yr#' + i, staticClass: this.today.year === i ? 'q-date__today' : null, ref: viewTarget === i ? 'viewTarget' : void 0, props: { @@ -1140,6 +1147,7 @@ export default Vue.extend({ staticClass: 'col-auto' }, [ h(QBtn, { + key: 'y-', props: { round: true, dense: true, @@ -1153,6 +1161,7 @@ export default Vue.extend({ ]), h('div', { + key: 'kNavYM', staticClass: 'q-date__years-content col self-stretch row items-center', directives: cache(this, 'kNavYM', [{ name: 'key-group-navigation', @@ -1164,6 +1173,7 @@ export default Vue.extend({ staticClass: 'col-auto' }, [ h(QBtn, { + key: 'y+', props: { round: true, dense: true, diff --git a/ui/src/components/dialog-bottom-sheet/BottomSheet.js b/ui/src/components/dialog-bottom-sheet/BottomSheet.js index 68472b227d2e..74a9c5338917 100644 --- a/ui/src/components/dialog-bottom-sheet/BottomSheet.js +++ b/ui/src/components/dialog-bottom-sheet/BottomSheet.js @@ -166,6 +166,7 @@ export default Vue.extend({ ) return h(QDialog, { + key: 'dialog', ref: 'dialog', props: this.dialogProps, on: cache(this, 'hide', { diff --git a/ui/src/components/dialog-plugin/DialogPlugin.js b/ui/src/components/dialog-plugin/DialogPlugin.js index 32cac0b66a45..e2ca6810a9a0 100644 --- a/ui/src/components/dialog-plugin/DialogPlugin.js +++ b/ui/src/components/dialog-plugin/DialogPlugin.js @@ -148,6 +148,7 @@ export default Vue.extend({ getPrompt (h) { return [ h(QInput, { + key: 'prompt', props: { value: this.prompt.model, type: this.prompt.type, @@ -192,6 +193,7 @@ export default Vue.extend({ getOptions (h) { return [ h(QOptionGroup, { + key: 'opts', props: { value: this.options.model, type: this.options.type, @@ -211,12 +213,14 @@ export default Vue.extend({ const child = [] this.cancel && child.push(h(QBtn, { + key: 'cancel', props: this.cancelProps, attrs: { 'data-autofocus': this.focus === 'cancel' && this.hasForm !== true }, on: cache(this, 'cancel', { click: this.onCancel }) })) this.ok && child.push(h(QBtn, { + key: 'ok', props: this.okProps, attrs: { 'data-autofocus': this.focus === 'ok' && this.hasForm !== true }, on: cache(this, 'ok', { click: this.onOk }) @@ -303,6 +307,7 @@ export default Vue.extend({ } return h(QDialog, { + key: 'dialog', ref: 'dialog', props: { diff --git a/ui/src/components/expansion-item/QExpansionItem.js b/ui/src/components/expansion-item/QExpansionItem.js index 24407a98b322..292f1b81fef3 100644 --- a/ui/src/components/expansion-item/QExpansionItem.js +++ b/ui/src/components/expansion-item/QExpansionItem.js @@ -208,6 +208,7 @@ export default Vue.extend({ if (this.activeToggleIcon === true) { Object.assign(data, { + key: 'inpExt', attrs: { tabindex: 0, ...this.toggleAriaAttrs @@ -305,6 +306,7 @@ export default Vue.extend({ this.__getHeader(h), h(QSlideTransition, { + key: 'slide', props: { duration: this.duration }, on: cache(this, 'slide', { show: () => { this.$emit('after-show') }, diff --git a/ui/src/components/fab/QFab.js b/ui/src/components/fab/QFab.js index 3227880e291b..992ae4a55b0b 100644 --- a/ui/src/components/fab/QFab.js +++ b/ui/src/components/fab/QFab.js @@ -143,6 +143,7 @@ export default Vue.extend({ on: { ...this.qListeners } }, [ h(QBtn, { + key: 'tog', ref: 'trigger', class: this.formClass, props: { diff --git a/ui/src/components/file/QFile.js b/ui/src/components/file/QFile.js index db66fd2764a7..0440f7dd0f54 100644 --- a/ui/src/components/file/QFile.js +++ b/ui/src/components/file/QFile.js @@ -166,6 +166,7 @@ export default Vue.extend({ __getControl (h) { const data = { + key: 'target', ref: 'target', staticClass: 'q-field__native row items-center cursor-pointer', attrs: { @@ -215,7 +216,7 @@ export default Vue.extend({ return this.innerValue.length === 0 ? this.__getFiller(h) : this.innerValue.map((file, i) => h(QChip, { - key: 'file-' + i, + key: 'rem#' + i, props: { removable: this.editable, dense: true, @@ -252,6 +253,7 @@ export default Vue.extend({ __getInput (h) { const data = { + key: 'input', ref: 'input', staticClass: 'q-field__input fit absolute-full cursor-pointer', attrs: this.inputAttrs, diff --git a/ui/src/components/footer/QFooter.js b/ui/src/components/footer/QFooter.js index 4e01b9650542..34d3ae5cbb18 100644 --- a/ui/src/components/footer/QFooter.js +++ b/ui/src/components/footer/QFooter.js @@ -150,6 +150,7 @@ export default Vue.extend({ render (h) { const child = mergeSlot([ h(QResizeObserver, { + key: 'resize', props: { debounce: 0 }, on: cache(this, 'resize', { resize: this.__onResize }) }) diff --git a/ui/src/components/header/QHeader.js b/ui/src/components/header/QHeader.js index da990c8ef62c..5d2d8672c8b1 100644 --- a/ui/src/components/header/QHeader.js +++ b/ui/src/components/header/QHeader.js @@ -144,6 +144,7 @@ export default Vue.extend({ child.push( h(QResizeObserver, { + key: 'resize', props: { debounce: 0 }, on: cache(this, 'resize', { resize: this.__onResize }) }) diff --git a/ui/src/components/knob/QKnob.js b/ui/src/components/knob/QKnob.js index 63c54e928e6e..2499688cb367 100644 --- a/ui/src/components/knob/QKnob.js +++ b/ui/src/components/knob/QKnob.js @@ -279,6 +279,7 @@ export default Vue.extend({ } if (this.editable === true) { + data.key = 'dir' data.on = this.onEvents data.directives = cache(this, 'dir', [{ name: 'touch-pan', diff --git a/ui/src/components/layout/QLayout.js b/ui/src/components/layout/QLayout.js index daaf1dec0213..0c3a432ce6c9 100644 --- a/ui/src/components/layout/QLayout.js +++ b/ui/src/components/layout/QLayout.js @@ -141,10 +141,12 @@ export default Vue.extend({ on: { ...this.qListeners } }, mergeSlot([ h(QScrollObserver, { + key: 'scroll', on: cache(this, 'scroll', { scroll: this.__onPageScroll }) }), h(QResizeObserver, { + key: 'resizeOut', on: cache(this, 'resizeOut', { resize: this.__onPageResize }) }) ], this, 'default')) @@ -154,6 +156,7 @@ export default Vue.extend({ staticClass: 'q-layout-container overflow-hidden' }, [ h(QResizeObserver, { + key: 'resizeIn', on: cache(this, 'resizeIn', { resize: this.__onContainerResize }) }), h('div', { diff --git a/ui/src/components/option-group/QOptionGroup.js b/ui/src/components/option-group/QOptionGroup.js index aa78c96d57e9..d020335d9c56 100644 --- a/ui/src/components/option-group/QOptionGroup.js +++ b/ui/src/components/option-group/QOptionGroup.js @@ -119,6 +119,7 @@ export default Vue.extend({ return h('div', [ h(this.component, { + key: 'inp', props: { value: this.value, val: opt.value, diff --git a/ui/src/components/pagination/QPagination.js b/ui/src/components/pagination/QPagination.js index f2e6e7714b71..4cf66b9092c4 100644 --- a/ui/src/components/pagination/QPagination.js +++ b/ui/src/components/pagination/QPagination.js @@ -468,6 +468,7 @@ export default Vue.extend({ ...contentStart, h('div', { + key: 'stop', staticClass: 'q-pagination__middle row justify-center', on: this.input === true ? cache(this, 'stop', { input: stop }) @@ -475,6 +476,7 @@ export default Vue.extend({ }, this.input === true ? [ h(QInput, { + key: 'inp', staticClass: 'inline', style: { width: `${this.inputPlaceholder.length / 1.5}em` }, props: { diff --git a/ui/src/components/popup-edit/QPopupEdit.js b/ui/src/components/popup-edit/QPopupEdit.js index a344af23969b..af15e345df01 100644 --- a/ui/src/components/popup-edit/QPopupEdit.js +++ b/ui/src/components/popup-edit/QPopupEdit.js @@ -153,6 +153,7 @@ export default Vue.extend({ this.buttons === true && child.push( h('div', { staticClass: 'q-popup-edit__buttons row justify-center no-wrap' }, [ h(QBtn, { + key: 'cancel', props: { flat: true, color: this.color, @@ -161,6 +162,7 @@ export default Vue.extend({ on: cache(this, 'cancel', { click: this.cancel }) }), h(QBtn, { + key: 'ok', props: { flat: true, color: this.color, @@ -179,6 +181,7 @@ export default Vue.extend({ if (this.disable === true) { return } return h(QMenu, { + key: 'menu', ref: 'menu', props: this.menuProps, on: cache(this, 'menu', { diff --git a/ui/src/components/radio/QRadio.js b/ui/src/components/radio/QRadio.js index adb4c900e0aa..108458a8c0e4 100644 --- a/ui/src/components/radio/QRadio.js +++ b/ui/src/components/radio/QRadio.js @@ -182,6 +182,7 @@ export default Vue.extend({ ) return h('div', { + key: 'inpExt', class: this.classes, attrs: this.attrs, on: cache(this, 'inpExt', { diff --git a/ui/src/components/rating/QRating.js b/ui/src/components/rating/QRating.js index 78890a0fcd86..dd5aab3b21ee 100644 --- a/ui/src/components/rating/QRating.js +++ b/ui/src/components/rating/QRating.js @@ -226,7 +226,7 @@ export default Vue.extend({ child.push( h('div', { - key: i, + key: 'i#' + i, ref: `rt${i}`, staticClass: 'q-rating__icon-container flex flex-center', attrs, diff --git a/ui/src/components/resize-observer/QResizeObserver.js b/ui/src/components/resize-observer/QResizeObserver.js index b1cdb30ab302..5ccbacd20e00 100644 --- a/ui/src/components/resize-observer/QResizeObserver.js +++ b/ui/src/components/resize-observer/QResizeObserver.js @@ -86,6 +86,7 @@ export default Vue.extend({ } return h('object', { + key: 'load', style: this.style, attrs: { tabindex: -1, // fix for Firefox diff --git a/ui/src/components/scroll-area/QScrollArea.js b/ui/src/components/scroll-area/QScrollArea.js index 5ea44728b280..580691160d87 100644 --- a/ui/src/components/scroll-area/QScrollArea.js +++ b/ui/src/components/scroll-area/QScrollArea.js @@ -474,6 +474,7 @@ export default Vue.extend({ render (h) { return h('div', { + key: 'desk', class: this.classes, on: cache(this, 'desk', { mouseenter: this.__mouseEnter, @@ -490,23 +491,27 @@ export default Vue.extend({ style: this.mainStyle }, mergeSlot([ h(QResizeObserver, { + key: 'resizeIn', props: { debounce: 0 }, on: cache(this, 'resizeIn', { resize: this.__updateScrollSize }) }) ], this, 'default')), h(QScrollObserver, { + key: 'scroll', props: { axis: 'both' }, on: cache(this, 'scroll', { scroll: this.__updateScroll }) }) ]), h(QResizeObserver, { + key: 'resizeOut', props: { debounce: 0 }, on: cache(this, 'resizeOut', { resize: this.__updateContainer }) }), h('div', { + key: 'barV', class: this.verticalBarClass, style: [ this.barStyle, this.verticalBarStyle ], attrs: ariaHidden, @@ -516,6 +521,7 @@ export default Vue.extend({ }), h('div', { + key: 'barH', class: this.horizontalBarClass, style: [ this.barStyle, this.horizontalBarStyle ], attrs: ariaHidden, diff --git a/ui/src/components/slide-transition/QSlideTransition.js b/ui/src/components/slide-transition/QSlideTransition.js index 1d046034d763..37f3a16c5a00 100644 --- a/ui/src/components/slide-transition/QSlideTransition.js +++ b/ui/src/components/slide-transition/QSlideTransition.js @@ -52,6 +52,7 @@ export default Vue.extend({ render (h) { return h('transition', { + key: 'tr', props: { css: false, appear: this.appear diff --git a/ui/src/components/splitter/QSplitter.js b/ui/src/components/splitter/QSplitter.js index 678b8d9daaec..1407a3c34a31 100644 --- a/ui/src/components/splitter/QSplitter.js +++ b/ui/src/components/splitter/QSplitter.js @@ -285,6 +285,7 @@ export default Vue.extend({ const child = [ h('div', { + key: 'before', ref: 'before', staticClass: 'q-splitter__panel q-splitter__before' + (this.reverse === true ? ' col' : ''), style: this.styles.before, @@ -308,6 +309,7 @@ export default Vue.extend({ ]), h('div', { + key: 'after', ref: 'after', staticClass: 'q-splitter__panel q-splitter__after' + (this.reverse === true ? '' : ' col'), style: this.styles.after, diff --git a/ui/src/components/stepper/QStepper.js b/ui/src/components/stepper/QStepper.js index 4bbd74228843..18985c66a81c 100644 --- a/ui/src/components/stepper/QStepper.js +++ b/ui/src/components/stepper/QStepper.js @@ -65,6 +65,7 @@ export default Vue.extend({ this.__isValidPanelName(this.value) && this.__updatePanelIndex() const content = h('div', { + key: 'stop', staticClass: 'q-stepper__content', // stop propagation of content emitted @input // which would tamper with Panel's model diff --git a/ui/src/components/stepper/StepHeader.js b/ui/src/components/stepper/StepHeader.js index 3547d30b8a57..d588b3789a68 100644 --- a/ui/src/components/stepper/StepHeader.js +++ b/ui/src/components/stepper/StepHeader.js @@ -129,6 +129,7 @@ export default Vue.extend({ } this.headerNav === true && Object.assign(data, { + key: 'headnavon', on: cache(this, 'headnavon', { click: this.activate, keyup: this.keyup diff --git a/ui/src/components/table/QTable.js b/ui/src/components/table/QTable.js index 0bf6b3dbca9a..a239a9269b61 100644 --- a/ui/src/components/table/QTable.js +++ b/ui/src/components/table/QTable.js @@ -321,6 +321,7 @@ export default Vue.extend({ } return h(QVirtualScroll, { + key: 'vs', ref: 'virtScroll', props: { ...this.virtProps, diff --git a/ui/src/components/table/table-bottom.js b/ui/src/components/table/table-bottom.js index 4a240961ecd3..4f603272c01e 100644 --- a/ui/src/components/table/table-bottom.js +++ b/ui/src/components/table/table-bottom.js @@ -103,6 +103,7 @@ export default { this.rowsPerPageLabel || this.$q.lang.table.recordsPerPage ]), h(QSelect, { + key: 'pgSize', staticClass: 'q-table__select inline q-table__bottom-item', props: { color: this.color, diff --git a/ui/src/components/table/table-header.js b/ui/src/components/table/table-header.js index e949ba841957..118742b42472 100644 --- a/ui/src/components/table/table-header.js +++ b/ui/src/components/table/table-header.js @@ -65,6 +65,7 @@ export default { ? slot(this.__getHeaderScope({})) : [ h(QCheckbox, { + key: 'inp', props: { color: this.color, value: this.headerSelectedValue, diff --git a/ui/src/components/tabs/QTabs.js b/ui/src/components/tabs/QTabs.js index 571f8b33bd44..04419e36b7d5 100644 --- a/ui/src/components/tabs/QTabs.js +++ b/ui/src/components/tabs/QTabs.js @@ -710,10 +710,12 @@ export default Vue.extend({ render (h) { const child = [ h(QResizeObserver, { + key: 'resize', on: cache(this, 'resize', { resize: this.__updateContainer }) }), h('div', { + key: 'scroll', ref: 'content', class: this.innerClass, on: this.arrowsEnabled === true ? cache(this, 'scroll', { scroll: this.__updateArrowsFn }) : void 0 @@ -722,6 +724,7 @@ export default Vue.extend({ this.arrowsEnabled === true && child.push( h(QIcon, { + key: 'onS', class: 'q-tabs__arrow q-tabs__arrow--start absolute q-tab__icon' + (this.leftArrow === true ? '' : ' q-tabs__arrow--faded'), props: { name: this.leftIcon || this.$q.iconSet.tabs[ this.vertical === true ? 'up' : 'left' ] }, @@ -735,6 +738,7 @@ export default Vue.extend({ }), h(QIcon, { + key: 'onE', class: 'q-tabs__arrow q-tabs__arrow--end absolute q-tab__icon' + (this.rightArrow === true ? '' : ' q-tabs__arrow--faded'), props: { name: this.rightIcon || this.$q.iconSet.tabs[ this.vertical === true ? 'down' : 'right' ] }, diff --git a/ui/src/components/time/QTime.js b/ui/src/components/time/QTime.js index 25ca6fef74e8..eb8e52da8f97 100644 --- a/ui/src/components/time/QTime.js +++ b/ui/src/components/time/QTime.js @@ -648,6 +648,7 @@ export default Vue.extend({ __getHeader (h) { const label = [ h('div', { + key: 'vH', staticClass: 'q-time__link', class: this.view === 'Hour' ? 'q-time__link--active' : 'cursor-pointer', attrs: { tabindex: this.computedTabindex, 'data-autofocus': this.view === 'Hour' }, @@ -664,6 +665,7 @@ export default Vue.extend({ 'div', this.minLink === true ? { + key: 'vM', ref: 'Minute', staticClass: 'q-time__link', class: this.view === 'Minute' ? 'q-time__link--active' : 'cursor-pointer', @@ -687,6 +689,7 @@ export default Vue.extend({ 'div', this.secLink === true ? { + key: 'vS', ref: 'Second', staticClass: 'q-time__link', class: this.view === 'Second' ? 'q-time__link--active' : 'cursor-pointer', @@ -716,6 +719,7 @@ export default Vue.extend({ staticClass: 'q-time__header-ampm column items-between no-wrap' }, [ h('div', { + key: 'AM', staticClass: 'q-time__link', class: this.isAM === true ? 'q-time__link--active' : 'cursor-pointer', attrs: { tabindex: this.computedTabindex }, @@ -726,6 +730,7 @@ export default Vue.extend({ }, [ 'AM' ]), h('div', { + key: 'PM', staticClass: 'q-time__link', class: this.isAM !== true ? 'q-time__link--active' : 'cursor-pointer', attrs: { tabindex: this.computedTabindex }, @@ -758,6 +763,7 @@ export default Vue.extend({ staticClass: 'q-time__container-child fit overflow-hidden' }, [ h('div', { + key: 'click', staticClass: 'q-time__clock cursor-pointer non-selectable', on: cache(this, 'click', { click: this.__click, @@ -793,6 +799,7 @@ export default Vue.extend({ ]), this.nowBtn === true ? h(QBtn, { + key: 'now', staticClass: 'q-time__now-button absolute', props: { icon: this.$q.iconSet.datetime.now, diff --git a/ui/src/components/tree/QTree.js b/ui/src/components/tree/QTree.js index a9182522426f..e7e9454cc228 100644 --- a/ui/src/components/tree/QTree.js +++ b/ui/src/components/tree/QTree.js @@ -603,6 +603,7 @@ export default Vue.extend({ this.noTransition === true ? getChildren() : h(QSlideTransition, { + key: 'slide', props: { duration: this.duration }, on: cache(this, 'slide', { show: () => { this.$emit('after-show') }, diff --git a/ui/src/components/uploader/QUploaderBase.js b/ui/src/components/uploader/QUploaderBase.js index 37fc990e5f59..803ef59f6927 100644 --- a/ui/src/components/uploader/QUploaderBase.js +++ b/ui/src/components/uploader/QUploaderBase.js @@ -290,6 +290,7 @@ export default Vue.extend({ __getInputControl (h) { return [ h('input', { + key: 'input', ref: 'input', staticClass: 'q-uploader__input overflow-hidden absolute-full', attrs: { @@ -436,6 +437,7 @@ export default Vue.extend({ ) return h('div', { + key: 'drag', staticClass: 'q-uploader column no-wrap', class: { [`q-uploader--${this.darkSuffix} q-${this.darkSuffix}`]: true, diff --git a/ui/src/mixins/checkbox.js b/ui/src/mixins/checkbox.js index a85e9b191d0e..4b822330bb1b 100644 --- a/ui/src/mixins/checkbox.js +++ b/ui/src/mixins/checkbox.js @@ -214,6 +214,7 @@ export default { ) return h('div', { + key: 'inpExt', class: this.classes, attrs: this.attrs, on: cache(this, 'inpExt', { diff --git a/ui/src/mixins/file.js b/ui/src/mixins/file.js index 119b44482885..3e083dd39774 100644 --- a/ui/src/mixins/file.js +++ b/ui/src/mixins/file.js @@ -207,6 +207,7 @@ export default { __getDnd (h, type) { if (this.dnd === true) { return h('div', { + key: 'dnd', staticClass: `q-${type}__dnd absolute-full`, ref: 'dnd', on: cache(this, 'dnd', { diff --git a/ui/src/mixins/panel.js b/ui/src/mixins/panel.js index 5b13c6df1bb0..d0adf23cd98e 100644 --- a/ui/src/mixins/panel.js +++ b/ui/src/mixins/panel.js @@ -12,6 +12,7 @@ import cache, { cacheWithFn } from '../utils/private/cache.js' function getPanelWrapper (h) { return h('div', { + key: 'stop', staticClass: 'q-panel scroll', // stop propagation of content emitted @input // which would tamper with Panel's model diff --git a/ui/src/plugins/Loading.js b/ui/src/plugins/Loading.js index eb9cdc591608..38d100e87774 100644 --- a/ui/src/plugins/Loading.js +++ b/ui/src/plugins/Loading.js @@ -86,6 +86,7 @@ const Loading = { render: (h) => { return h('transition', { + key: 'tr', props: { name: 'q-transition--fade', appear: true