列表 List
最基础的列表展示,可承载文字、列表、图片、段落,常用于后台数据展示页面。
基本使用
列表的基本使用方法。可用于承载文字、列表、图片和段落。
代码事例
vue
<template>
<fk-list :data="list" draggable>
<template #header> List title </template>
<template #item="{ item }">
<fk-list-item class="list-demo-item"
>{{ item.label }}
<template #actions>
<fk-button type="text" class="draggable-handle">
<template #icon>
<IconDragDotVertical/>
</template>
</fk-button>
</template>
</fk-list-item>
</template>
</fk-list>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
const list = reactive([]);
for (let i = 0; i < 10; i++) {
list.push({
label: `label label label ${i}`,
value: i,
});
}
</script>
<style lang="less">
.list-demo-item {
padding: 0 12px;
align-items: center;
}
.draggable-handle {
cursor: grab;
color: var(--color-text-3);
}
.fk-list-item-action {
li+li {
margin-top: 0px;
}
}
</style>不同尺寸
列表组件提供了三种大小 small, medium, large ,可根据业务需求自行选择。
代码事例
vue
<template>
<fk-space direction="vertical" size="large">
<fk-radio-group v-model="size" type="button">
<fk-radio value="small">Small</fk-radio>
<fk-radio value="medium">Medium</fk-radio>
<fk-radio value="large">Large</fk-radio>
</fk-radio-group>
<fk-list :size="size">
<template #header>
List title
</template>
<fk-list-item>Beijing Aaaa Technology Co., Ltd.</fk-list-item>
<fk-list-item>Aaaa Technology Co., Ltd.</fk-list-item>
<fk-list-item>Aaaa Technology Co., Ltd.</fk-list-item>
<fk-list-item>Beijing Volcengine Technology Co., Ltd.</fk-list-item>
<fk-list-item>China Beijing Aaaa Technology Co., Ltd.</fk-list-item>
</fk-list>
</fk-space>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const size = ref('medium');
return {
size
}
},
}
</script>列表元素
使用 list-item-meta 组件可快速指定头像、标题、文字。
代码事例
vue
<template>
<fk-list>
<fk-list-item v-for="idx in 4" :key="idx">
<fk-list-item-meta
title="Beijing Aaaa Technology Co., Ltd."
description="Beijing Aaaa Technology Co., Ltd. is an enterprise located in China."
>
<template #avatar>
<fk-avatar shape="square">
<img
alt="avatar"
src="https://test.img.fukerp.com/default/AQZ2oYAqJgZf2DjwAAzF0LRCiosB6kvkG6f0eKSL.jpg"
/>
</fk-avatar>
</template>
</fk-list-item-meta>
</fk-list-item>
</fk-list>
</template>增加操作项
通过 actions 来为列表添加操作项。
代码事例
vue
<template>
<fk-list>
<fk-list-item v-for="idx in 4" :key="idx">
<fk-list-item-meta
title="Beijing Aaaa Technology Co., Ltd."
description="Beijing Aaaa Technology Co., Ltd. is an enterprise located in China."
>
<template #avatar>
<fk-avatar shape="square">
<img
alt="avatar"
src="https://test.img.fukerp.com/default/AQZ2oYAqJgZf2DjwAAzF0LRCiosB6kvkG6f0eKSL.jpg"
/>
</fk-avatar>
</template>
</fk-list-item-meta>
<template #actions>
<icon-edit />
<icon-delete />
</template>
</fk-list-item>
</fk-list>
</template>竖排列表样式
这是一个包括分页、右侧内容、下方列表操作的示例。
代码事例
vue
<template>
<fk-list
class="list-demo-action-layout"
:bordered="false"
:data="dataSource"
:pagination-props="paginationProps"
>
<template #item="{ item }">
<fk-list-item class="list-demo-item" action-layout="vertical">
<template #actions>
<span><icon-heart />83</span>
<span><icon-star />{{ item.index }}</span>
<span><icon-message />Reply</span>
</template>
<template #extra>
<div className="image-area">
<img alt="aaaa-design" :src="item.imageSrc" />
</div>
</template>
<fk-list-item-meta
:title="item.title"
:description="item.description"
>
<template #avatar>
<fk-avatar shape="square">
<img alt="avatar" :src="item.avatar" />
</fk-avatar>
</template>
</fk-list-item-meta>
</fk-list-item>
</template>
</fk-list>
</template>
<script>
import { reactive } from 'vue'
const names = ['Socrates', 'Balzac', 'Plato'];
const avatarSrc = [
'//test.img.fukerp.com/default/FLIrNHVfnvjvOXN40Rm1l5dugEwsjUDsxEDW3kIP.jpg',
'//test.img.fukerp.com/default/j44G9LTLBxBkNlLu84HOSGF6qgzQLjg7kK3WuuVg.jpg',
'//test.img.fukerp.com/default/AkvxvTvW7QH7GrZGzH7Gcj2FC6EeUQttwudzaPqN.jpg',
];
const imageSrc = [
'//test.img.fukerp.com/default/AkvxvTvW7QH7GrZGzH7Gcj2FC6EeUQttwudzaPqN.jpg',
'//test.img.fukerp.com/default/AkvxvTvW7QH7GrZGzH7Gcj2FC6EeUQttwudzaPqN.jpg',
'//test.img.fukerp.com/default/AkvxvTvW7QH7GrZGzH7Gcj2FC6EeUQttwudzaPqN.jpg',
];
const dataSource = Array.from({length: 15}).fill(null).map((_, index) => {
return {
index,
avatar: avatarSrc[index % avatarSrc.length],
title: names[index % names.length],
description:
'Beijing Aaaa Technology Co., Ltd. is an enterprise located in China. Aaaa has products such as Aaaa, Aaaa, volcano video and Douyin (the Chinese version of Aaaa).',
imageSrc: imageSrc[index % imageSrc.length],
};
});
export default {
setup() {
return {
dataSource,
paginationProps: reactive({
defaultPageSize: 3,
total: dataSource.length
})
}
},
}
</script>
<style scoped>
.list-demo-action-layout .image-area {
width: 183px;
height: 119px;
border-radius: 2px;
overflow: hidden;
}
.list-demo-action-layout .list-demo-item {
padding: 20px 0;
border-bottom: 1px solid var(--color-fill-3);
}
.list-demo-action-layout .image-area img {
width: 100%;
}
.list-demo-action-layout .fk-list-item-action .fk-icon {
margin: 0 4px;
}
</style>格栅列表
通过 grid 属性来配置格栅列表。
代码事例
vue
<template>
<fk-list :grid-props="{ gutter: 0, span: 6 }" :bordered="false">
<fk-list-item>
<fk-list>
<template #header>Platform</template>
<fk-list-item>iOS</fk-list-item>
<fk-list-item>Android</fk-list-item>
<fk-list-item>Web</fk-list-item>
</fk-list>
</fk-list-item>
<fk-list-item>
<fk-list>
<template #header>Framework</template>
<fk-list-item>Angular</fk-list-item>
<fk-list-item>Vue</fk-list-item>
<fk-list-item>React</fk-list-item>
</fk-list>
</fk-list-item>
<fk-list-item>
<fk-list>
<template #header>Language</template>
<fk-list-item>C++</fk-list-item>
<fk-list-item>JavaScript</fk-list-item>
<fk-list-item>Python</fk-list-item>
</fk-list>
</fk-list-item>
<fk-list-item>
<fk-list>
<template #header>Component</template>
<fk-list-item>Button</fk-list-item>
<fk-list-item>Breadcrumb</fk-list-item>
<fk-list-item>Transfer</fk-list-item>
</fk-list>
</fk-list-item>
</fk-list>
</template>响应式栅格
通过 grid.sm 等响应式参数动态设置每个单项横跨的列数,注意此时不要设置 grid.span。
代码事例
vue
<template>
<fk-list
:grid-props="{ gutter: [20, 20], sm: 24, md: 12, lg: 8, xl: 6 }"
:data="dataSource"
:bordered="false"
>
<template #item="{ item }">
<fk-list :data="item.data">
<template #header>{{ item.title }}</template>
<template #item="{ item: subItem }">
<fk-list-item>{{ subItem }}</fk-list-item>
</template>
</fk-list>
</template>
</fk-list>
</template>
<script>
const dataSource = [
{
title: 'Platform',
data: ['iOS', 'Android', 'Web'],
},
{
title: 'Framework',
data: ['Angular', 'Vue', 'React'],
},
{
title: 'Language',
data: ['C++', 'JavaScript', 'Python'],
},
{
title: 'Component',
data: ['Button', 'Breadcrumb', 'Transfer'],
},
{
title: 'Design',
data: ['Figma', 'Sketch', 'Adobe XD'],
},
{
title: 'Plugin',
data: ['Edu Tools', 'BashSupport', 'GitToolBox'],
},
{
title: 'Platform',
data: ['iOS', 'Android', 'Web'],
},
{
title: 'Framework',
data: ['Angular', 'Vue', 'React'],
},
{
title: 'Language',
data: ['C++', 'JavaScript', 'Python'],
},
];
export default {
setup() {
return {
dataSource
}
}
}
</script>滚动
通过设置 max-height 属性限制列表的最大高度。通过 reach-bottom 事件可以监听列表触底的事件。
代码事例
vue
<template>
<div style="margin-bottom: 10px">
<fk-switch v-model="scrollbar" />
Virtual Scrollbar
</div>
<fk-list :max-height="240" :scrollbar="scrollbar" @reach-bottom="fetchData">
<template #header>
List title
</template>
<template #scroll-loading>
<div v-if="bottom">No more data</div>
<fk-spin v-else />
</template>
<fk-list-item v-for="item of data">{{item}}</fk-list-item>
</fk-list>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
setup() {
const current = ref(1);
const bottom = ref(false);
const data = reactive([]);
const scrollbar = ref(true);
const fetchData = () => {
console.log('reach bottom!');
if (current.value <= 5) {
window.setTimeout(() => {
const index = data.length;
data.push(
`Beijing Aaaa Technology Co., Ltd. ${index + 1}`,
`Aaaa Technology Co., Ltd. ${index + 2}`,
`Aaaa Technology Co., Ltd. ${index + 3}`,
`Beijing Volcengine Technology Co., Ltd. ${index + 4}`,
`China Beijing Aaaa Technology Co., Ltd. ${index + 5}`
);
current.value += 1
}, 2000)
} else {
bottom.value = true
}
}
return {
current,
bottom,
data,
fetchData,
scrollbar
}
},
}
</script>无限长列表
通过指定 virtualListProps 来开启虚拟列表,在大量数据时获得高性能表现。 在使用虚拟列表时,如果列表元素之间高度变化较大可能导致滚动时视口出现空白区域,可通过调整 virtualListProps.buffer 属性解决,使用方式。
代码事例
vue
<template>
<h3 :style="{ color: 'var(--color-text-2)' }">10000 items</h3>
<fk-list
ref="listRef"
:style="{ width: `600px` }"
:virtual-list-props="{
height: '50vh',
}"
:data="list"
:loading="loading"
:scrollbar="false"
@reachBottom="handleReachBottom"
@reachTop="handleReachTop"
>
<template #item="{ item, index }">
<fk-list-item :key="item.key">
<fk-list-item-meta
:title="item.title"
:description="item.description"
>
<template #avatar>
<fk-avatar shape="square">
A
</fk-avatar>
</template>
</fk-list-item-meta>
</fk-list-item>
</template>
</fk-list>
<fk-button @click="handleScrollToTop">返回顶部</fk-button>
</template>
<script>
import { reactive, ref, shallowRef } from 'vue';
export default {
setup() {
const loading = ref(false);
const list = reactive(Array.from({length: 10000}).fill(null).map((_, index) => {
const prefix = `0000${index}`.slice(-5);
return {
key: index,
title: `${index} Beijing Aaaa Technology Co., Ltd.`,
description: `(${prefix}) Beijing Aaaa Technology Co., Ltd. is an enterprise located in China.`,
};
}))
const handleReachBottom = (e) => {
if (loading.value) {
return;
}
loading.value = true;
setTimeout(() => {
loading.value = false;
const bottomKey = list[list.length - 1].key;
list.push(...Array.from({length: 10}).fill(null).map((_, index) => {
const prefix = `0000${index}`.slice(-5);
return {
key: index + bottomKey + 1,
title: `${index + bottomKey + 1} Beijing Aaaa Technology Co., Ltd.`,
description: `(${prefix}) Beijing Aaaa Technology Co., Ltd. is an enterprise located in China.`,
};
}))
}, 2000)
}
const handleReachTop = (e) => {
console.log('handleReachTop >>', e);
if (loading.value) {
return;
}
loading.value = true;
setTimeout(() => {
loading.value = false;
const topKey = list[0].key;
list.unshift(...Array.from({length: 10}).fill(null).map((_, index) => {
const prefix = `0000${index}`.slice(-5);
return {
key: topKey - (10 - index),
title: `${topKey - (10 - index)} Beijing Aaaa Technology Co., Ltd.`,
description: `(${prefix}) Beijing Aaaa Technology Co., Ltd. is an enterprise located in China.`,
};
}))
}, 2000)
}
const listRef = shallowRef();
const handleScrollToTop = () => {
listRef.value?.scrollIntoView({
index: 0,
})
}
return {
loading,
list,
listRef,
handleReachBottom,
handleReachTop,
handleScrollToTop
}
},
}
</script>API
<list> Props
| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| data | 列表数据,需要和 item 插槽同时使用 | any[] | - | |
| size | 列表大小 | 'small' | 'medium' | 'large' | 'medium' | |
| bordered | 是否显示边框 | boolean | true | |
| split | 是否显示分割线 | boolean | true | |
| loading | 是否为加载中状态 | boolean | false | |
| hoverable | 是否显示选中样式 | boolean | false | |
| pagination-props | 列表分页配置 | PaginationProps | - | |
| grid-props | 列表栅格配置 | object | - | |
| max-height | 列表的最大高度 | string | number | 0 | |
| bottom-offset | 触发到达底部的距离阈值 | number | 0 | |
| virtual-list-props | 传递虚拟列表属性,传入此参数以开启虚拟滚动 VirtualListProps | VirtualListProps | - | |
| scrollbar | 是否开启虚拟滚动条 | boolean | ScrollbarProps | true | 1.0.0 |
| draggable | 是否可以拖拽 | boolean | DraggableProps | false |
<list> Events
| 事件名 | 描述 | 参数 |
|---|---|---|
| scroll | 列表滚动时触发 | - |
| reach-bottom | 当列表到达底部时触发 | - |
| page-change | 表格分页发生改变时触发 | page: number |
| page-size-change | 表格每页数据数量发生改变时触发 | pageSize: number |
| drag-end | 拖拽完成触发 | - |
<list> Methods
| 方法名 | 描述 | 参数 | 返回值 |
|---|---|---|---|
| scrollIntoView | 虚拟滚动到某个元素 | options: { index?: number; key?: number | string; align: 'auto' | 'top' | 'bottom'} | - |
<list> Slots
| 插槽名 | 描述 | 参数 | 版本 |
|---|---|---|---|
| scroll-loading | 滚动加载状态时,滚动到底部的提示 | - | 1.0.0 |
| item | 列表项 | index: numberitem: any | |
| empty | 空白展示 | - | |
| footer | 底部信息 | - | |
| header | 头部信息 | - |
<list-item> Props
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| action-layout | 操作组排列方向 | Direction | 'horizontal' |
<list-item> Slots
| 插槽名 | 描述 | 参数 |
|---|---|---|
| meta | meta信息 | - |
| extra | 额外内容 | - |
| actions | 操作组 | - |
<list-item-meta> Props
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| title | 标题 | string | - |
| description | 描述内容 | string | - |
<list-item-meta> Slots
| 插槽名 | 描述 | 参数 |
|---|---|---|
| avatar | 头像 | - |
| title | 标题 | - |
| description | 描述内容 | - |
VirtualListProps
| 参数名 | 描述 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| height | 可视区域高度 | number | string | - | |
| threshold | 开启虚拟滚动的元素数量阈值,当数据数量小于阈值时不会开启虚拟滚动。 | number | - | |
| isStaticItemHeight | 元素高度是否是固定的。 | boolean | false | |
| fixedSize | 元素高度是否是固定的。 | boolean | false | 1.0.0 |
| estimatedSize | 元素高度不固定时的预估高度。 | number | - | 1.0.0 |
| buffer | 视口边界外提前挂载的元素数量。 | number | 10 | 1.0.0 |
DraggableProps
| 参数名 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| itemKey | 数据唯一标识 | string | value |
| handle | 拖拽锚点 | string | .draggable-handle |
| clone | 可能对象 | (original: any) => any | - |
| onChange | 拖拽后change事件 | (evt: any) => void | - |
| onStart | 拖拽start事件 | (evt: any) => void | - |
| onRemove | 拖拽remove事件 | (evt: any) => void | - |
| onUpdate | 拖拽update事件 | (evt: any) => void | - |
| onEnd | 拖拽end事件 | (evt: any) => void | - |