diff --git a/src/components/table/helpers/mixin-tbody-row.js b/src/components/table/helpers/mixin-tbody-row.js index 88dc3f74b2e..f5f86f3bdc1 100644 --- a/src/components/table/helpers/mixin-tbody-row.js +++ b/src/components/table/helpers/mixin-tbody-row.js @@ -205,10 +205,11 @@ export default { // v-slot attributes are lower-cased by the browser. // Switched to round bracket syntax to prevent confusion with // dynamic slot name syntax. - const slotNames = [`cell(${key})`, `cell(${key.toLowerCase()})`, 'cell()'] - let $childNodes = this.hasNormalizedSlot(slotNames) - ? this.normalizeSlot(slotNames, slotScope) - : toString(formatted) + // We look for slots in this order: `cell(${key})`, `cell(${key.toLowerCase()})`, 'cell()' + // Slot names are now cached by mixin tbody in `this.$_bodyFieldSlotNameCache` + // Will be `null` if no slot (or fallback slot) exists + const slotName = this.$_bodyFieldSlotNameCache[key] + let $childNodes = slotName ? this.normalizeSlot(slotName, slotScope) : toString(formatted) if (this.isStacked) { // We wrap in a DIV to ensure rendered as a single cell when visually stacked! $childNodes = [h('div', {}, [$childNodes])] diff --git a/src/components/table/helpers/mixin-tbody.js b/src/components/table/helpers/mixin-tbody.js index fe304ed8a49..45e83bc07a0 100644 --- a/src/components/table/helpers/mixin-tbody.js +++ b/src/components/table/helpers/mixin-tbody.js @@ -30,6 +30,26 @@ export default { } else { // Table isn't busy, or we don't have a busy slot + // Create a slot cache for improved performace when looking up cell slot names. + // Values will be keyed by the field's `key` and will store the slot's name. + // Slots could be dynamic (i.e. `v-if`), so we must compute on each render. + // Used by tbodyRow mixin render helper. + const cache = {} + const defaultSlotName = this.hasNormalizedSlot('cell()') ? 'cell()' : null + this.computedFields.forEach(field => { + const key = field.key + const fullName = `cell(${key})` + const lowerName = `cell(${key.toLowerCase()})` + cache[key] = this.hasNormalizedSlot(fullName) + ? fullName + : this.hasNormalizedSlot(lowerName) + ? lowerName + : defaultSlotName + }) + // Created as a non-reactive property so to not trigger component updates. + // Must be a fresh object each render. + this.$_bodyFieldSlotNameCache = cache + // Add static Top Row slot (hidden in visibly stacked mode as we can't control data-label attr) $rows.push(this.renderTopRow ? this.renderTopRow() : h())