Would you like to buy me a βοΈ instead?
In one of my previous articles, we examined how we can use JSX in Vue.js to export multiple Vue.js components from a single Single File Component (SFC) .vue
file. Just recently I found an even easier solution to this problem.
Although it can be handy to use JSX for simple UI components, as I described in my article, there are some drawbacks to this approach. First, JSX doesn’t feel very natural in a Vue.js environment, and second, you lose many of the advantages of Vue.js Single File Components, such as scoped styles.
Proxy exports
The concept I’ve come up with is quite simple: All components live in their own SFC, but there is one master component that proxies all associated components.
Let’s say we have a custom form, and we want to split it up into multiple components for each part of the form.
components
ββ FancyTable.vue
ββ FancyTableBody.vue
ββ FancyTableCell.vue
ββ FancyTableHead.vue
ββ FancyTableRow.vue
If we want to use these generic form components to create a new, more specific component like a DataList
component, it will look something like this.
<template>
<FancyTable>
<!-- ... -->
</FancyTable>
</template>
<script>
// src/components/DataList.vue
import FancyTable from './FancyTable.vue';
import FancyTableBody from './FancyTableBody.vue';
import FancyTableCell from './FancyTableCell.vue';
import FancyTableHead from './FancyTableHead.vue';
import FancyTableRow from './FancyTableRow.vue';
// ...
</script>
Let’s improve this somewhat by updating our FancyTable
component to serve as a proxy component that also exports all associated components.
<template>
<table class="FancyTable">
<slot/>
</table>
</template>
<script>
// Export the root component as named export.
export const FancyTable = {
name: 'FancyTable',
// ...
};
// Proxy export all related components.
export { default as FancyTableBody } from './FancyTableBody.vue';
export { default as FancyTableCell } from './FancyTableCell.vue';
export { default as FancyTableHead } from './FancyTableHead.vue';
export { default as FancyTableRow } from './FancyTableRow.vue';
// A Vue.js SFC must have a default export.
export default FancyTable;
</script>
Now our FancyTable
component serves as a proxy for all related subcomponents. Shout-out to Philipp KΓΌhn for showing me this shortened export
/ from
syntax.
Do you want to learn more about advanced Vue.js techniques?
Register for the Newsletter of my upcoming book: Advanced Vue.js Application Architecture.
<template>
<FancyTable>
<!-- ... -->
</FancyTable>
</template>
<script>
// src/components/DataList.vue
import {
FancyTable,
FancyTableBody,
FancyTableCell,
FancyTableHead,
FancyTableRow,
} from './FancyTable.vue';
// ...
</script>
As you can see above, we now only have to use one import
statement to import all parts of the table we need to build our DataList
component.
Wrapping it up
The benefits of this approach are most likely not a big deal, but in my opinion it can still be a useful improvement in certain situations.
Situations in which I already use this pattern are for generic table components such as in the example above and also for form components such as various types of input and general form layout components.