Skip to content
Permalink
Browse files

perf(tables): make `b-th` extend `b-td` instead of using functional w…

…rappers (#4156)
  • Loading branch information...
tmorehouse committed Sep 25, 2019
1 parent 3f3a46c commit c9715a89b1d693974dff8db7e24f97cdf908ff99
Showing with 183 additions and 204 deletions.
  1. +0 −185 src/components/table/helpers/table-cell.js
  2. +177 −9 src/components/table/td.js
  3. +6 −10 src/components/table/th.js

This file was deleted.

@@ -1,17 +1,185 @@
import Vue from '../../utils/vue'
import { omit } from '../../utils/object'
import { props as cellProps, BTableCell } from './helpers/table-cell'
import toString from '../../utils/to-string'
import { isUndefinedOrNull } from '../../utils/inspect'
import normalizeSlotMixin from '../../mixins/normalize-slot'

export const props = omit(cellProps, ['header'])
const digitsRx = /^\d+$/

// Parse a rowspan or colspan into a digit (or null if < 1 or NaN)
const parseSpan = val => {
val = parseInt(val, 10)
return digitsRx.test(String(val)) && val > 0 ? val : null
}

/* istanbul ignore next */
const spanValidator = val => isUndefinedOrNull(val) || parseSpan(val) > 0

export const props = {
variant: {
type: String,
default: null
},
colspan: {
type: [Number, String],
default: null,
validator: spanValidator
},
rowspan: {
type: [Number, String],
default: null,
validator: spanValidator
},
stackedHeading: {
type: String,
default: null
},
stickyColumn: {
type: Boolean,
default: false
}
}

// @vue/component
export const BTd = /*#__PURE__*/ Vue.extend({
name: 'BTd',
functional: true,
name: 'BTableCell',
mixins: [normalizeSlotMixin],
inheritAttrs: false,
inject: {
// Injections for feature / attribute detection
bvTable: {
default: null
},
bvTableTbody: {
default: null
},
bvTableThead: {
default: null
},
bvTableTfoot: {
default: null
},
bvTableTr: {
default: null
}
},
props,
render(h, { props, data, children }) {
// `data` already includes any listeners
data.props = { ...props, header: false }
return h(BTableCell, data, children)
computed: {
tag() {
// Overridden by <b-th>
return 'td'
},
isDark() {
return this.bvTable && this.bvTable.dark
},
isStacked() {
return this.bvTable && this.bvTable.isStacked
},
isStackedCell() {
// We only support stacked-heading in tbody in stacked mode
return this.bvTableTbody && this.isStacked
},
isResponsive() {
return this.bvTable && this.bvTable.isResponsive && !this.isStacked
},
isStickyHeader() {
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
// Sticky headers only apply to cells in table `thead`
return (
!this.isStacked &&
this.bvTable &&
this.bvTableThead &&
this.bvTableTr &&
this.bvTable.stickyHeader
)
},
isStickyColumn() {
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
// Sticky column cells are only available in responsive
// mode (horizontal scrolling) or when sticky header mode
// Applies to cells in `thead`, `tbody` and `tfoot`
return (
(this.isResponsive || this.isStickyHeader) &&
this.stickyColumn &&
!this.isStacked &&
this.bvTable &&
this.bvTableTr
)
},
cellClasses() {
// We use computed props here for improved performance by caching
// the results of the string interpolation
let variant = this.variant
if (
(!variant && this.isStickyHeader && !this.bvTableThead.headVariant) ||
(!variant && this.isStickyColumn)
) {
// Needed for sticky-header mode as Bootstrap v4 table cells do
// not inherit parent's background-color. Boo!
variant = this.bvTableTr.variant || this.bvTable.tableVariant || 'b-table-default'
}
return [
variant ? `${this.isDark ? 'bg' : 'table'}-${variant}` : null,
this.isStickyColumn ? 'b-table-sticky-column' : null
]
},
computedColspan() {
return parseSpan(this.colspan)
},
computedRowspan() {
return parseSpan(this.rowspan)
},
cellAttrs() {
// We use computed props here for improved performance by caching
// the results of the object spread (Object.assign)
const headOrFoot = this.bvTableThead || this.bvTableTfoot
// Make sure col/rowspan's are > 0 or null
const colspan = this.computedColspan
const rowspan = this.computedRowspan
// Default role and scope
let role = 'cell'
let scope = null

// Compute role and scope
// We only add scopes with an explicit span of 1 or greater
if (headOrFoot) {
// Header or footer cells
role = 'columnheader'
scope = colspan > 0 ? 'colspan' : 'col'
} else if (this.tag === 'th') {
// th's in tbody
role = 'rowheader'
scope = rowspan > 0 ? 'rowgroup' : 'row'
}

return {
colspan: colspan,
rowspan: rowspan,
role: role,
scope: scope,
// Allow users to override role/scope plus add other attributes
...this.$attrs,
// Add in the stacked cell label data-attribute if in
// stacked mode (if a stacked heading label is provided)
'data-label':
this.isStackedCell && !isUndefinedOrNull(this.stackedHeading)
? toString(this.stackedHeading)
: null
}
}
},
render(h) {
const content = [this.normalizeSlot('default')]
return h(
this.tag,
{
class: this.cellClasses,
attrs: this.cellAttrs,
// Transfer any native listeners
on: this.$listeners
},
[this.isStackedCell ? h('div', [content]) : content]
)
}
})

0 comments on commit c9715a8

Please sign in to comment.
You can’t perform that action at this time.