Skip to content

Commit

Permalink
feat(cdk:scroll): virtual scroll supports horizontal (#1775)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: itemHeight is deprecated, use rowHeight instead
BREAKING CHANGE: itemRender is deprecated, use rowRender instead
  • Loading branch information
sallerli1 committed Jan 2, 2024
1 parent 655cb21 commit 77a0411
Show file tree
Hide file tree
Showing 47 changed files with 1,769 additions and 398 deletions.
Empty file modified .husky/commit-msg 100755 → 100644
Empty file.
Empty file modified .husky/pre-commit 100755 → 100644
Empty file.
Empty file modified packages/cdk/platform/src/platform.ts 100755 → 100644
Empty file.
@@ -1,21 +1,21 @@
// Vitest Snapshot v1

exports[`VirtualScroll > basic work > itemRender work 1`] = `
exports[`VirtualScroll > basic work > render work 1`] = `
"<div class=\\"cdk-virtual-scroll\\">
<div class=\\"cdk-virtual-scroll-holder\\" style=\\"max-height: 200px;\\">
<div class=\\"cdk-virtual-scroll-filler\\" style=\\"height: 400px;\\">
<div class=\\"cdk-virtual-scroll-content\\" style=\\"transform: translateY(0px); position: absolute; left: 0px; right: 0px; top: 0px;\\"><span class=\\"virtual-item\\">key-0 - 0</span><span class=\\"virtual-item\\">key-1 - 1</span><span class=\\"virtual-item\\">key-2 - 2</span><span class=\\"virtual-item\\">key-3 - 3</span><span class=\\"virtual-item\\">key-4 - 4</span><span class=\\"virtual-item\\">key-5 - 5</span><span class=\\"virtual-item\\">key-6 - 6</span><span class=\\"virtual-item\\">key-7 - 7</span><span class=\\"virtual-item\\">key-8 - 8</span><span class=\\"virtual-item\\">key-9 - 9</span><span class=\\"virtual-item\\">key-10 - 10</span><span class=\\"virtual-item\\">key-11 - 11</span></div>
</div>
<div class=\\"cdk-virtual-scroll-holder\\" style=\\"max-height: 200px; width: 100%;\\">
<!---->
<div class=\\"cdk-virtual-scroll-filler-vertical\\" style=\\"height: 400px; width: 0px;\\"></div>
<div class=\\"cdk-virtual-scroll-content\\" style=\\"margin-top: 0px; margin-left: 0px;\\"><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-0 - 0</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-1 - 1</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-2 - 2</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-3 - 3</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-4 - 4</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-5 - 5</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-6 - 6</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-7 - 7</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-8 - 8</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-9 - 9</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-10 - 10</span></div>
</div>
</div>"
`;
exports[`VirtualScroll > basic work > render work 1`] = `
exports[`VirtualScroll > basic work > rowRender work 1`] = `
"<div class=\\"cdk-virtual-scroll\\">
<div class=\\"cdk-virtual-scroll-holder\\" style=\\"max-height: 200px;\\">
<div class=\\"cdk-virtual-scroll-filler\\" style=\\"height: 400px;\\">
<div class=\\"cdk-virtual-scroll-content\\" style=\\"transform: translateY(0px); position: absolute; left: 0px; right: 0px; top: 0px;\\"><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-0 - 0</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-1 - 1</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-2 - 2</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-3 - 3</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-4 - 4</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-5 - 5</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-6 - 6</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-7 - 7</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-8 - 8</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-9 - 9</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-10 - 10</span><span class=\\"virtual-item\\" style=\\"height: 20px;\\">key-11 - 11</span></div>
</div>
<div class=\\"cdk-virtual-scroll-holder\\" style=\\"max-height: 200px; width: 100%;\\">
<!---->
<div class=\\"cdk-virtual-scroll-filler-vertical\\" style=\\"height: 400px; width: 0px;\\"></div>
<div class=\\"cdk-virtual-scroll-content\\" style=\\"margin-top: 0px; margin-left: 0px;\\"><span class=\\"virtual-item\\">key-0 - 0</span><span class=\\"virtual-item\\">key-1 - 1</span><span class=\\"virtual-item\\">key-2 - 2</span><span class=\\"virtual-item\\">key-3 - 3</span><span class=\\"virtual-item\\">key-4 - 4</span><span class=\\"virtual-item\\">key-5 - 5</span><span class=\\"virtual-item\\">key-6 - 6</span><span class=\\"virtual-item\\">key-7 - 7</span><span class=\\"virtual-item\\">key-8 - 8</span><span class=\\"virtual-item\\">key-9 - 9</span><span class=\\"virtual-item\\">key-10 - 10</span></div>
</div>
</div>"
`;
24 changes: 12 additions & 12 deletions packages/cdk/scroll/__tests__/virtualScroll.spec.ts
Expand Up @@ -2,7 +2,7 @@ import { MountingOptions, VueWrapper, flushPromises, mount } from '@vue/test-uti
import { h } from 'vue'

import VirtualScroll from '../src/virtual/VirtualScroll'
import { VirtualItemRenderFn, VirtualScrollInstance, VirtualScrollProps } from '../src/virtual/types'
import { VirtualRowRenderFn, VirtualScrollInstance, VirtualScrollProps } from '../src/virtual/types'

const getData = (length: number, key = 'key') => {
const data: { key: string }[] = []
Expand All @@ -14,12 +14,12 @@ const getData = (length: number, key = 'key') => {

const defaultProps = {
height: 200,
itemHeight: 20,
rowHeight: 20,
getKey: 'key',
} as const

const defaultItemSlot = `
<template #item="{ item, index }">
<template #row="{ item, index }">
<span class="virtual-item" style="height: 20px;">{{ item.key }} - {{ index }}</span>
</template>
`
Expand Down Expand Up @@ -86,7 +86,7 @@ describe('VirtualScroll', () => {

await wrapper.setProps({ dataSource: getData(15) })

expect(wrapper.findAll('.virtual-item').length).toEqual(12)
expect(wrapper.findAll('.virtual-item').length).toEqual(11)
})

test('fullHeight work', async () => {
Expand Down Expand Up @@ -118,12 +118,12 @@ describe('VirtualScroll', () => {
await wrapper.setProps({ dataSource: getData(20) })

expect(wrapper.find('.cdk-virtual-scroll-holder').attributes('style')).toContain('height: 200px')
expect(wrapper.findAll('.virtual-item').length).toEqual(12)
expect(wrapper.findAll('.virtual-item').length).toEqual(11)

await wrapper.setProps({ height: 300 })

expect(wrapper.find('.cdk-virtual-scroll-holder').attributes('style')).toContain('height: 300px')
expect(wrapper.findAll('.virtual-item').length).toEqual(17)
expect(wrapper.findAll('.virtual-item').length).toEqual(16)
})

test('itemHeight work', async () => {
Expand All @@ -136,11 +136,11 @@ describe('VirtualScroll', () => {

await wrapper.setProps({ dataSource: getData(30) })

expect(wrapper.findAll('.virtual-item').length).toEqual(12)
expect(wrapper.findAll('.virtual-item').length).toEqual(11)

await wrapper.setProps({ itemHeight: 10 })
await wrapper.setProps({ rowHeight: 10 })

expect(wrapper.findAll('.virtual-item').length).toEqual(22)
expect(wrapper.findAll('.virtual-item').length).toEqual(21)
})

test('getKey work', async () => {
Expand All @@ -156,13 +156,13 @@ describe('VirtualScroll', () => {
wrapper.findAll('.virtual-item').forEach((item, index) => expect(item.text()).toEqual(`key-${index} - ${index}`))
})

test('itemRender work', async () => {
const itemRender: VirtualItemRenderFn = ({ item, index }) => {
test('rowRender work', async () => {
const rowRender: VirtualRowRenderFn = ({ item, index }) => {
const { key } = item as { key: string }
return h('span', { class: 'virtual-item' }, [`${key} - ${index}`])
}
const wrapper = VirtualScrollMount({
props: { dataSource: getData(20), itemRender },
props: { dataSource: getData(20), rowRender },
})

expect(wrapper.html()).toMatchSnapshot()
Expand Down
6 changes: 4 additions & 2 deletions packages/cdk/scroll/demo/Basic.vue
Expand Up @@ -4,13 +4,15 @@
ref="listRef"
:dataSource="data"
:height="200"
:itemHeight="20"
:rowHeight="20"
:bufferSize="20"
:bufferOffset="5"
getKey="key"
@scroll="onScroll"
@scrolledChange="onScrolledChange"
@scrolledBottom="onScrolledBottom"
>
<template #item="{ item, index }">
<template #row="{ item, index }">
<span class="virtual-item" @click="onItemClick(item.key)">{{ item.key }} - {{ index }}</span>
</template>
</CdkVirtualScroll>
Expand Down
14 changes: 14 additions & 0 deletions packages/cdk/scroll/demo/Both.md
@@ -0,0 +1,14 @@
---
title:
zh: 横向&竖向虚拟滚动
en: Horizontal & vertical virtual scroll
order: 3
---

## zh

开启横向以及竖向虚拟滚动的场景。

## en

Use horizontal and vertical virtual scroll.
77 changes: 77 additions & 0 deletions packages/cdk/scroll/demo/Both.vue
@@ -0,0 +1,77 @@
<template>
<div class="demo-both-scroll-wrapper">
<CdkVirtualScroll
ref="listRef"
:dataSource="rowData"
:height="200"
:rowHeight="20"
:colWidth="200"
:virtual="true"
:rowRender="rowRender"
getKey="key"
>
<template #col="{ row, item, index }">
<span class="virtual-item" @click="onItemClick(item.key)">{{ row.key }} - {{ index }}</span>
</template>
</CdkVirtualScroll>
</div>
</template>

<script setup lang="ts">
import { h, ref } from 'vue'
import { VirtualRowRenderFn, VirtualScrollInstance, VirtualScrollRowData } from '@idux/cdk/scroll'
const listRef = ref<VirtualScrollInstance>()
const colData: { key: string }[] = []
for (let index = 0; index < 1000; index++) {
colData.push({ key: `col-key-${index}` })
}
const rowData: VirtualScrollRowData[] = []
for (let index = 0; index < 1000; index++) {
rowData.push({
key: `row-key-${index}`,
data: colData,
})
}
const rowRender: VirtualRowRenderFn = ({ children }) =>
h(
'div',
{
class: 'virtual-row',
},
children,
)
const onItemClick = (key: string) => {
console.log('click:', key)
}
</script>

<style lang="less">
.demo-both-scroll-wrapper {
height: 240px;
.cdk-virtual-scroll {
border: 1px solid red;
margin-bottom: 8px;
}
.virtual-row {
flex-shrink: 0;
display: flex;
height: 20px;
flex-wrap: nowrap;
border: 1px solid gray;
}
.virtual-item {
flex-shrink: 0;
padding-left: 16px;
border: 1px solid gray;
height: 100%;
width: 200px;
line-height: 18px;
}
}
</style>
14 changes: 14 additions & 0 deletions packages/cdk/scroll/demo/Horizontal.md
@@ -0,0 +1,14 @@
---
title:
zh: 横向虚拟滚动
en: Horizontal virtual scroll
order: 2
---

## zh

仅开启横向虚拟滚动的场景。

## en

Only use horizontal virtual scroll.
93 changes: 93 additions & 0 deletions packages/cdk/scroll/demo/Horizontal.vue
@@ -0,0 +1,93 @@
<template>
<div class="demo-horizontal-scroll-wrapper">
<CdkVirtualScroll
ref="listRef"
:dataSource="rowData"
:height="200"
:fullHeight="true"
:colWidth="80"
:bufferSize="20"
:bufferOffset="5"
:virtual="{ vertical: false, horizontal: true }"
:rowRender="rowRender"
getKey="key"
@scroll="onScroll"
@scrolledChange="onScrolledChange"
@scrolledBottom="onScrolledBottom"
>
<template #col="{ item, index }">
<span class="virtual-item" @click="onItemClick(item.key)">{{ item.key }} - {{ index }}</span>
</template>
</CdkVirtualScroll>
</div>
</template>

<script setup lang="ts">
import { h, ref } from 'vue'
import { VirtualRowRenderFn, VirtualScrollInstance } from '@idux/cdk/scroll'
const listRef = ref<VirtualScrollInstance>()
const data: { key: string }[] = []
for (let index = 0; index < 1000; index++) {
data.push({ key: `key-${index}` })
}
const rowData = [
{
key: 'row',
data,
},
]
const rowRender: VirtualRowRenderFn = ({ children }) =>
h(
'div',
{
class: 'virtual-row',
style: { display: 'flex', height: '100%', 'flex-wrap': 'nowrap' },
},
children,
)
const onScroll = (evt: Event) => {
console.log('scroll:', evt)
}
const onScrolledChange = (startIndex: number, endIndex: number, visibleData: { key: string }[]) =>
console.log('onScrolledChange', startIndex, endIndex, visibleData)
const onScrolledBottom = () => console.log('onScrolledBottom')
const onItemClick = (key: string) => {
console.log('click:', key)
}
</script>

<style lang="less">
.demo-horizontal-scroll-wrapper {
height: 240px;
.cdk-virtual-scroll {
border: 1px solid red;
margin-bottom: 8px;
}
.cdk-virtual-scroll-content {
height: 100%;
}
.virtual-row {
display: flex;
height: 100%;
flex-wrap: nowrap;
}
.virtual-item {
flex-shrink: 0;
padding-left: 16px;
border: 1px solid gray;
height: 100%;
width: 80px;
line-height: 18px;
}
}
</style>
6 changes: 3 additions & 3 deletions packages/cdk/scroll/demo/Switch.vue
@@ -1,5 +1,5 @@
<template>
<CdkVirtualScroll :dataSource="data" :height="height" getKey="key" :itemHeight="20" :itemRender="itemRender">
<CdkVirtualScroll :dataSource="data" :height="height" getKey="key" :rowHeight="20" :rowRender="itemRender">
</CdkVirtualScroll>

<IxSpace>
Expand Down Expand Up @@ -33,7 +33,7 @@
<script setup lang="ts">
import { computed, h, ref } from 'vue'
import { VirtualItemRenderFn } from '@idux/cdk/scroll'
import { VirtualRowRenderFn } from '@idux/cdk/scroll'
const getData = (length: number, key = 'key') => {
const data: { key: string }[] = []
Expand All @@ -47,7 +47,7 @@ const dataLength = ref(20)
const data = computed(() => getData(dataLength.value))
const height = ref(200)
const switchItemRender = ref(false)
const itemRender = computed<VirtualItemRenderFn>(() => {
const itemRender = computed<VirtualRowRenderFn>(() => {
if (switchItemRender.value) {
return ({ item }) => h('div', { style: { height: '20px', paddingLeft: '8px' } }, [`${item.key}`])
} else {
Expand Down

0 comments on commit 77a0411

Please sign in to comment.