Skip to main content

How do you optimize large tables?

1. Don't render everything at once: pagination

The simplest approach:

  • show only part of the data (10-50 rows per page)
  • the rest, through buttons/pagination/"show more"
vue
<tr v-for="row in paginatedRows" :key="row.id"> ... </tr>
js
const page = ref(1) const perPage = 50 const paginatedRows = computed(() => { const start = (page.value - 1) * perPage return rows.value.slice(start, start + perPage) })

Even better: server-side pagination, fetching only the needed page from the backend.


2. Virtualization / windowing (viewport-only rendering)

For very large tables (10k+ rows) you need virtual scrolling:

  • only the visible rows plus a small buffer above/below are rendered in the DOM
  • the rest is just empty space with the correct height

In Vue, libraries like these are usually used:

  • vue-virtual-scroller
  • vue-virtual-scroll-list

An example of the idea (illustrative):

vue
<VirtualList :data-key="'id'" :data-sources="rows" :data-component="RowComponent" :kept-alive="50" />

This drastically reduces the number of DOM elements.


3. Minimize data reactivity

If the table simply displays data and the rows themselves aren't edited:

  • you don't need to make every row super-reactive
  • you can use:
    • markRaw for large objects/arrays
    • shallowRef for the whole list
js
import { shallowRef, markRaw } from 'vue' const rows = shallowRef([]) // if huge objects arrive: rows.value = markRaw(bigArray)

This way Vue won't deeply track every nested field.


4. A proper key in v-for

Always:

vue
<tr v-for="row in rows" :key="row.id">
  • a stable, unique key → Vue reuses rows
  • fewer DOM element recreations
  • better performance during filtering/sorting

Don't use the index as the key (:key="index") if rows can be added/removed/reordered.


5. Heavy logic goes into computed, not the template

Don't do this:

vue
<td>{{ formatPrice(row.price) }}</td> <td>{{ complexCalculation(row) }}</td>

Better:

  • precompute the data ahead of time in computed
  • or prepare the fields before passing them into the table
js
const preparedRows = computed(() => rows.value.map(row => ({ ...row, priceLabel: formatPrice(row.price), total: calcTotal(row) })) )

6. Don't create new objects/functions in the template

Every render:

vue
<Cell :options="{ align: 'right' }" />

creates a new object → Vue thinks the prop changed → unnecessary updates.

Extract such data:

js
const rightAlignOptions = { align: 'right' }
vue
<Cell :options="rightAlignOptions" />

7. Optimize filtering and sorting

  • filters/search → debounce on input
  • sorting/filtering → in computed, not in a watch deep over the whole array
  • for huge data, delegate sorting and filtering to the server
js
const debouncedQuery = ref('') watch(query, debounce((v) => { debouncedQuery.value = v }, 300))

8. Simplify cell content

Inside <td>:

  • fewer complex components
  • don't render what the user won't see anyway (conditional blocks, expand-on-click)
  • lazy details: expand details/detail cards only on request

9. Don't pull everything into the global store "just in case"

If a huge table is stored in the global store:

  • any store change can trigger many components
  • it's better to keep such data local to the page/module

10. Visually: skeletons and lazy-loading

From a UX standpoint:

  • show a skeleton instead of the full table
  • load data in chunks
  • don't block the UI

This isn't strictly a "render optimization", but it greatly improves perception.


How to phrase this in an interview (briefly):

To optimize large tables in Vue, I:

  • use pagination or virtual scrolling so I don't render thousands of rows at once;
  • minimize reactivity (shallowRef/markRaw for large structures);
  • watch the key in v-for so Vue reuses rows;
  • move heavy computations into computed and avoid creating new objects/functions in the template;
  • when needed, do filtering and sorting on the server, and debounce input.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.