Search code examples
vue.jscomponents

Way to remove custom component code repetition in Vue?


My custom component code:

<template>
<div class="event">
    <div class="title text">
        {{ title }}
    </div>
    <div class="date text">
        {{ date }}
    </div>
    <div class="time text">
        {{ time }}
    </div>
    <div class="address text">
        {{ address }}
    </div>
    <div class="learn-more text">
        Learn more!
    </div>
</div>
<script>
export default {
    name: 'EventCard',
    props: {
        title: { 
            type: String, 
            required: true, 
            default: ''
        }, 
        date: { 
            type: String, 
            required: false, 
            default: ''
        },
        time: { 
            type: String, 
            required: true, 
            default: ''
        },
        address: { 
            type: String, 
            required: true, 
            default: ''
        },
        type: {
            type: String,
            required: true,
            default: ''
        }
    }
}

with some styling as well.

I am then using this custom component in an EventDiscoveryPage.vue file where I have the code written as such:

        <div class="events">
        <EventCard class="food-event" :title="'food event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="middle-row-event music-event" :title="'music event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="music-event" :title="'music event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="comedy-event" :title="'comedy event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="middle-row-event music-event" :title="'music event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="food-event" :title="'food event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="music-event" :title="'music event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="middle-row-event comedy-event" :title="'comedy event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
        <EventCard class="comedy-event" :title="'comedy event'" :date="'date-test'" :time="'time-test'" :address="'address-test'" :type="'music'" />
    </div>

As of right now, the code works as intended, but I am wanting to reduce this seemingly redundant code and was wondering if I am able to use a v-for in some way to automate this process a little bit more, but I wasn't sure because I saw that v-for required preset data? I wasn't able to figure out using the documentation and was wondering if anyone had any recommendations.


Solution

  • You can refactor your code using a v-for iterating over an array of objects like this:

    <template>
      <div class="events">
        <EventCard v-for="event in events" :key="event.title" :class="event.class" :title="event.title" :date="event.date" :time="event.time" :address="event.address" :type="event.type" />
      </div>
    </template>
    
    <script>
    export default {
      data () {
        return {
          events: [
            { class: 'food-event', title: 'food event', date: 'date-test', time: 'time-test', address: 'address-test', type: 'music' },
            { class: '...', title: '...', date: '...', time: '...', address: '...', type: '...' },
            ...
          ]
        }
      }
    }
    </script>