feat: add new Guide for renderingLargeData

This commit is contained in:
hrynevych.romann 2024-02-20 22:48:28 +02:00
parent b09910fb2e
commit 79a344626e
12 changed files with 57 additions and 25946 deletions

View File

@ -23,11 +23,6 @@ const examples = [
href: '/examples/tasks',
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/tasks',
},
{
name: 'Tasks (Big Data)',
href: '/examples/big-data',
code: 'https://github.com/radix-vue/shadcn-vue/tree/dev/apps/www/src/examples/big-data',
},
{
name: 'Playground',
href: '/examples/playground',

View File

@ -353,6 +353,16 @@ export const docsConfig: DocsConfig = {
},
],
},
{
title: 'Guides',
items: [
{
title: 'Render Large Data',
href: '/docs/guides/rendering-large-data',
items: [],
},
],
},
],
}

View File

@ -0,0 +1,29 @@
---
title: Rendering Large Data
description: In some cases, you may need to render a large amount of data. This can be done using the useVirtualList Component from VueUse library to render only the visible items. This can help to improve performance.
sidebar: false
---
## How to render large data
When you have a large amount of data to render, you can use the [useVirtualList](https://vueuse.org/core/useVirtualList/#usevirtuallist) Component from [VueUse](https://vueuse.org/) library to render only the visible items. This can help to improve performance.
`useVirtualList` waiting for a `MaybeRef<T[]>` so firstly you need to wrap your data with `ref` or `computed` function. So we will convert our `table.getRowModel().rows` to `computed` function.
<<< @/examples/big-data/components/DataTable.vue#tableRows{ts}
Next step is to create a `useVirtualList` instance and pass our `tableRows` to it. For better experience list elements must be same height, which you define inside `itemHeight` property. `overscan` property is used to define how many items should be rendered outside of the visible area.
<<< @/examples/big-data/components/DataTable.vue#useVirtualList{2-3 ts}
## Example
Here is an example of how to use `useVirtualList` to render a large amount of data. For test purposes, we will use 2000 rows for our table, you can change statuses, priorities, and view to see speed difference.
<script setup>
import BigDataExample from "@/examples/big-data/Example.vue"
</script>
<Suspense>
<BigDataExample />
</Suspense>

View File

@ -1,5 +0,0 @@
<script setup>
import BigDataExample from "@/examples/big-data/Example.vue"
</script>
<BigDataExample />

View File

@ -1,36 +1,11 @@
<script setup lang="ts">
import tasks from './data/tasks.json'
import DataTable from './components/DataTable.vue'
import UserNav from './components/UserNav.vue'
import { columns } from './components/columns'
const response = await fetch('https://api.json-generator.com/templates/NttPDOzDwSsS/data?access_token=xi78iyv3ez1qwmm9pgou7r5mbqxfxrfmdzcps0hm')
const tasks = await response.json()
</script>
<template>
<div class="md:hidden">
<VPImage
alt="Tasks"
width="1280"
height="1214" class="block" :image="{
dark: '/examples/tasks-dark.png',
light: '/examples/tasks-light.png',
}"
/>
</div>
<div class="hidden h-full flex-1 flex-col space-y-8 p-8 md:flex">
<div class="flex items-center justify-between space-y-2">
<div>
<h2 class="text-2xl font-bold tracking-tight">
Welcome back!
</h2>
<p class="text-muted-foreground">
Here&apos;s a list of your tasks for this month!
</p>
</div>
<div class="flex items-center space-x-2">
<UserNav />
</div>
</div>
<DataTable :data="tasks" :columns="columns" />
</div>
<DataTable :data="tasks" :columns="columns" />
</template>

View File

@ -70,12 +70,16 @@ const table = useVueTable({
},
})
// #region tableRows
const tableRows = computed(() => table.getRowModel().rows)
// #endregion tableRows
// #region useVirtualList
const { list, containerProps, wrapperProps } = useVirtualList(tableRows, {
itemHeight: 49,
overscan: 15,
})
// #endregion useVirtualList
</script>
<template>
@ -85,7 +89,7 @@ const { list, containerProps, wrapperProps } = useVirtualList(tableRows, {
<Table v-bind="wrapperProps">
<TableHeader style="height: 49px">
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
<TableHead v-for="header in headerGroup.headers" :key="header.id">
<TableHead v-for="header in headerGroup.headers" :key="header.id" class="sticky top-0 bg-black z-10 border-b">
<FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header" :props="header.getContext()" />
</TableHead>
</TableRow>

View File

@ -5,6 +5,7 @@ import ArrowDownIcon from '~icons/radix-icons/arrow-down'
import ArrowUpIcon from '~icons/radix-icons/arrow-up'
import CaretSortIcon from '~icons/radix-icons/caret-sort'
import EyeNoneIcon from '~icons/radix-icons/eye-none'
import ResetIcon from '~icons/radix-icons/reset'
import { cn } from '@/lib/utils'
import { Button } from '@/lib/registry/new-york/ui/button'
@ -59,6 +60,10 @@ export default {
<EyeNoneIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Hide
</DropdownMenuItem>
<DropdownMenuItem v-if="column.getIsSorted()" @click="column.clearSorting()">
<ResetIcon class="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
Reset
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>

View File

@ -20,8 +20,8 @@ const isFiltered = computed(() => props.table.getState().columnFilters.length >
</script>
<template>
<div class="flex items-center justify-between">
<div class="flex flex-1 items-center space-x-2">
<div class="flex items-start justify-between flex-wrap">
<div class="flex flex-1 items-center gap-2 flex-wrap">
<Input
placeholder="Filter tasks..."
:model-value="(table.getColumn('title')?.getFilterValue() as string) ?? ''"

View File

@ -34,7 +34,7 @@ export const columns: ColumnDef<Task>[] = [
return h('div', { class: 'flex space-x-2' }, [
label && h(Badge, { variant: 'outline' }, label.label),
h('span', { class: 'max-w-[500px] truncate font-medium' }, row.getValue('title')),
h('span', { class: 'max-w-[180px] truncate font-medium' }, row.getValue('title')),
])
},
},

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ defineProps<DataTablePaginationProps>()
<SelectValue :placeholder="`${table.getState().pagination.pageSize}`" />
</SelectTrigger>
<SelectContent side="top">
<SelectItem v-for="pageSize in [10, 20, 30, 40, 50, 100, 1000]" :key="pageSize" :value="`${pageSize}`">
<SelectItem v-for="pageSize in [10, 20, 30, 40, 50]" :key="pageSize" :value="`${pageSize}`">
{{ pageSize }}
</SelectItem>
</SelectContent>

File diff suppressed because it is too large Load Diff