<div id="app">
  <v-table v-bind="tableConfig">
    <template v-slot:index="{ index }">
      {{ index + 1 }}
    </template>
    <template v-slot:name="{ cell }">
      <v-tag>{{ cell }}</v-tag>
    </template>  
    <template v-slot:iron="{ cell }">
      {{ cell }}%
    </template>  
    <template v-slot:action="{ row }">
      <button class="btn" @click="handleClick(row)">Actions</button>
    </template>  
  </v-table>
</div>
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');

body {
  font-family: 'Roboto', sans-serif;
}

table {
  width: 100%;
  margin: 10px;
  border-spacing: 0px;
}

thead td {
  font-weight: bold;
}

td {
  padding: 8px;
  border-bottom: 1px solid #eee;
}

.tag {
  background: #38A169;
  color: white;
  font-size: 0.8em;
  padding: 3px 5px;
  border-radius: 5px;
}

.btn {
  padding: 5px 8px;
  border-radius: 5px;
  background: #2D3748;
  color: white;
  border: 0;
}
View Compiled
Vue.component("v-tag", {
  template: `<span class="tag"><slot /></span>` 
});
Vue.component("v-table", {
  props: {
    headers: {
      type: Array,
      required: true
    },
    items: {
      type: Array,
      required: true
    }
  },
  template: `
  <table>
    <thead>
      <tr class="data-table-row">
        <td v-for="(header, i) in headers" :key="i">{{ header.text }}</td>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(row, j) in items" :key="'row_' + j">
        <template v-for="(header, k) in headers">
          <td :key="k">
            <slot
              v-if="$scopedSlots[header.key]"
              :name="header.key"
              :cell="row[header.key]"
              :row="row"
              :index="j"
            />
            <template v-else>
              {{ row[header.key] }}
            </template>
          </td>
        </template>
      </tr>
    </tbody>
  </table>
  `
});

var app = new Vue({
  el: "#app",
  data: {
    tableConfig: {
      headers: [
        { text: "", key: "index" },
        {
          text: "Dessert (100g serving)",
          key: "name"
        },
        { text: "Calories", key: "calories" },
        { text: "Fat (g)", key: "fat" },
        { text: "Carbs (g)", key: "carbs" },
        { text: "Protein (g)", key: "protein" },
        { text: "Iron (%)", key: "iron" },
        { text: "", key: "action" }
          
      ],
      items: [
        {
          name: "Frozen Yogurt",
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          iron: 1
        },
        {
          name: "Ice cream sandwich",
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          iron: 1
        },
        {
          name: "Eclair",
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          iron: 7
        },
        {
          name: "Cupcake",
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          iron: 8
        },
        {
          name: "Gingerbread",
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          iron: 16
        },
        {
          name: "Jelly bean",
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          iron: 0
        },
        {
          name: "Lollipop",
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          iron: 2
        },
        {
          name: "Honeycomb",
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          iron: 45
        },
        {
          name: "Donut",
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          iron: 22
        },
        {
          name: "KitKat",
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          iron: 6
        }
      ]
    }
  },
  methods: {
    handleClick(item){
      console.log(item)
    }
  }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.jsdelivr.net/npm/vue@2.6.11