Wednesday, March 24, 2021

Quickly factoring out a component in vue.js

If your single file component has grown too large and unwieldy, it might be time to refactor it, and parcel out a portion to a sub-component. In order to minimize the amount of coding in doin so things can be kept to a minimum like this:

  • a new component is created, and referenced in the parent
  • only the HTML is factored out in the sub-component
  • all parent data gets passed to the child
  • events stay in the parent element

First create a minimal new component, let’s call it list, like so:

<template>
  <div>
  </div>
</template>
<script>
</script>

The second step is quite simple: cut the parts you want to factor out of the parent component, and paste them in your new child component. So what in the parent component looked like this:

<table>
<!-- lots of stuff inside here -->
</table>

now becomes

<list></list>

with all the <table></table> code coing into the list component which then looks like this:

<template>
  <table>
    <!-- lots of stuff inside here -->
  </table>
</template>
<script>
module.exports = {
}
</script>

Then you ensure that all the parent data becomes child props. If your parent data looks like this:

data: function () {
    return {
        parts: [],
        blLookup: {},
        prices: {},
        skipParts: {},
        updateId: 0,
        totalCost: 0,
        totalPieces: 0,
        partCount: 0,
        partsFound: 0,
        config: { price: 'min', loc: 'EU', state: 'new' },
    };
},

your child props will look like this:

props: {
    parts: Array,
    blLookup: Object,
    prices: Object,
    skipParts: Object,
    updateId: Number,
    totalCost: Number,
    totalPieces: Number,
    partCount: Number,
    partsFound: Number,
    config: Object
},

Finally, you have to edit the component so that events are called at the parent level. What in the parent component looked like this:

<td><input @change="editPart($event, p.DesignID, i)" class="designID" :value="p.DesignID"></td>

in the child components needs to be changed like this:

<td><input @change="$parent.editPart($event, p.DesignID, i)" class="designID" :value="p.DesignID"></td>

so that the event calls a function inside the parent - as opposed to inside the component.

Now the final step - referencing the sub-component inside the parent, using the path from which the component is served - obviously.

components: {
    list: httpVueLoader('components/set/list.vue')
},

That’s it - you have factored out a part of your parent component in five easy steps.