Skip to content

列表 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是否显示边框booleantrue
split是否显示分割线booleantrue
loading是否为加载中状态booleanfalse
hoverable是否显示选中样式booleanfalse
pagination-props列表分页配置PaginationProps-
grid-props列表栅格配置object-
max-height列表的最大高度string | number0
bottom-offset触发到达底部的距离阈值number0
virtual-list-props传递虚拟列表属性,传入此参数以开启虚拟滚动 VirtualListPropsVirtualListProps-
scrollbar是否开启虚拟滚动条boolean | ScrollbarPropstrue1.0.0
draggable是否可以拖拽boolean | DraggablePropsfalse

<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: number
item: any
empty空白展示-
footer底部信息-
header头部信息-

<list-item> Props

参数名描述类型默认值
action-layout操作组排列方向Direction'horizontal'

<list-item> Slots

插槽名描述参数
metameta信息-
extra额外内容-
actions操作组-

<list-item-meta> Props

参数名描述类型默认值
title标题string-
description描述内容string-

<list-item-meta> Slots

插槽名描述参数
avatar头像-
title标题-
description描述内容-

VirtualListProps

参数名描述类型默认值版本
height可视区域高度number | string-
threshold开启虚拟滚动的元素数量阈值,当数据数量小于阈值时不会开启虚拟滚动。number-
isStaticItemHeight元素高度是否是固定的。booleanfalse
fixedSize元素高度是否是固定的。booleanfalse1.0.0
estimatedSize元素高度不固定时的预估高度。number-1.0.0
buffer视口边界外提前挂载的元素数量。number101.0.0

DraggableProps

参数名描述类型默认值
itemKey数据唯一标识stringvalue
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-

基于 MIT 许可发布