feat: add list component

This commit is contained in:
tjz 2018-06-16 21:30:41 +08:00
parent abbfb50f56
commit 90f5c8a9a9
25 changed files with 1916 additions and 3 deletions

View File

@ -59,6 +59,9 @@ const getSlots = (ele) => {
return slots
}
const getSlotOptions = (ele) => {
if (ele.fnOptions) { // 函数式组件
return ele.fnOptions
}
let componentOptions = ele.componentOptions
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions

View File

@ -60,7 +60,7 @@ import { default as InputNumber } from './input-number'
import { default as Layout } from './layout'
// import { default as List } from './list'
import { default as List } from './list'
import { default as LocaleProvider } from './locale-provider'
@ -163,6 +163,9 @@ const components = [
Layout.Footer,
Layout.Sider,
Layout.Content,
List,
List.Item,
List.Item.Meta,
LocaleProvider,
Menu,
Menu.Item,
@ -247,6 +250,7 @@ export {
Input,
InputNumber,
Layout,
List,
LocaleProvider,
Menu,
Modal,

143
components/list/Item.jsx Normal file
View File

@ -0,0 +1,143 @@
import PropTypes from '../_util/vue-types'
import classNames from 'classnames'
import { getSlotOptions, getComponentFromProp, isEmptyElement } from '../_util/props-util'
import { Col } from '../grid'
import { ListGridType } from './index'
export const ListItemProps = {
prefixCls: PropTypes.string,
extra: PropTypes.any,
actions: PropTypes.arrayOf(PropTypes.any),
grid: ListGridType,
}
export const ListItemMetaProps = {
avatar: PropTypes.any,
description: PropTypes.any,
prefixCls: PropTypes.string,
title: PropTypes.any,
}
export const Meta = {
functional: true,
name: 'AListItemMeta',
__ANT_LIST_ITEM_META: true,
render (h, context) {
const { props, slots, listeners } = context
const slotsMap = slots()
const {
prefixCls = 'ant-list',
} = props
const avatar = props.avatar || slotsMap.avatar
const title = props.title || slotsMap.title
const description = props.description || slotsMap.description
const content = (
<div class={`${prefixCls}-item-meta-content`}>
{title && <h4 class={`${prefixCls}-item-meta-title`}>{title}</h4>}
{description && <div class={`${prefixCls}-item-meta-description`}>{description}</div>}
</div>
)
return (
<div {...{ on: listeners }} class={`${prefixCls}-item-meta`}>
{avatar && <div class={`${prefixCls}-item-meta-avatar`}>{avatar}</div>}
{(title || description) && content}
</div>
)
},
}
function getGrid (grid, t) {
return grid[t] && Math.floor(24 / grid[t])
}
export default {
name: 'AListItem',
Meta,
props: ListItemProps,
inject: {
listContext: { default: {}},
},
render () {
const { grid } = this.listContext
const { prefixCls = 'ant-list', $slots, $listeners } = this
const classString = `${prefixCls}-item`
const extra = getComponentFromProp(this, 'extra')
const actions = getComponentFromProp(this, 'actions')
const metaContent = []
const otherContent = []
;($slots.default || []).forEach((element) => {
if (!isEmptyElement(element)) {
if (getSlotOptions(element).__ANT_LIST_ITEM_META) {
metaContent.push(element)
} else {
otherContent.push(element)
}
}
})
const contentClassString = classNames(`${prefixCls}-item-content`, {
[`${prefixCls}-item-content-single`]: (metaContent.length < 1),
})
const content = otherContent.length > 0 ? (
<div class={contentClassString}>
{otherContent}
</div>) : null
let actionsContent
if (actions && actions.length > 0) {
const actionsContentItem = (action, i) => (
<li key={`${prefixCls}-item-action-${i}`}>
{action}
{i !== (actions.length - 1) && <em class={`${prefixCls}-item-action-split`}/>}
</li>
)
actionsContent = (
<ul class={`${prefixCls}-item-action`}>
{actions.map((action, i) => actionsContentItem(action, i))}
</ul>
)
}
const extraContent = (
<div class={`${prefixCls}-item-extra-wrap`}>
<div class={`${prefixCls}-item-main`}>
{metaContent}
{content}
{actionsContent}
</div>
<div class={`${prefixCls}-item-extra`}>{extra}</div>
</div>
)
const mainContent = grid ? (
<Col
span={getGrid(grid, 'column')}
xs={getGrid(grid, 'xs')}
sm={getGrid(grid, 'sm')}
md={getGrid(grid, 'md')}
lg={getGrid(grid, 'lg')}
xl={getGrid(grid, 'xl')}
xxl={getGrid(grid, 'xxl')}
>
<div {...{ on: $listeners }} class={classString}>
{extra && extraContent}
{!extra && metaContent}
{!extra && content}
{!extra && actionsContent}
</div>
</Col>
) : (
<div {...{ on: $listeners }} class={classString}>
{extra && extraContent}
{!extra && metaContent}
{!extra && content}
{!extra && actionsContent}
</div>
)
return mainContent
},
}

View File

@ -0,0 +1,486 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/list/demo/basic.md correctly 1`] = `
<div class="ant-list ant-list-split">
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-list-item">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">Ant Design Title 1</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team</div>
</div>
</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">Ant Design Title 2</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team</div>
</div>
</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">Ant Design Title 3</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team</div>
</div>
</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">Ant Design Title 4</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/list/demo/grid.md correctly 1`] = `
<div class="ant-list ant-list-split ant-list-grid">
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-row" style="margin-left: -8px; margin-right: -8px;">
<div class="ant-col-6" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 1</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-6" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 2</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-6" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 3</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-6" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 4</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/list/demo/infinite-load.md correctly 1`] = `
<div infinite-scroll-distance="10" class="demo-infinite-container">
<div class="ant-list ant-list-split">
<div class="ant-spin ant-spin-show-text"><span class="ant-spin-dot"><i></i><i></i><i></i><i></i></span></div>
</div>
</div>
`;
exports[`renders ./components/list/demo/infinite-virtualized-load.md correctly 1`] = `
<div class="ant-list ant-list-split">
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div data-v-caa2d078="" class="virtual-scroller" infinite-scroll-distance="10" style="height: 400px;">
<div data-v-caa2d078="" class="item-container">
<div data-v-caa2d078="" class="items"></div>
</div>
<div data-v-b329ee4c="" data-v-caa2d078="" tabindex="-1" class="resize-observer">
<object style="display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;" aria-hidden="true" tabindex="-1" type="text/html" data="about:blank"></object>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/list/demo/loadmore.md correctly 1`] = `
<div class="demo-loadmore-list ant-list ant-list-split ant-list-loading ant-list-something-after-last-item">
<div class="ant-spin-nested-loading">
<div>
<div class="ant-spin ant-spin-spinning ant-spin-show-text"><span class="ant-spin-dot"><i></i><i></i><i></i><i></i></span></div>
</div>
<div class="ant-spin-container ant-spin-blur">
<div style="min-height: 53;"></div>
</div>
</div>
<div style="text-align: center; margin-top: 12px; height: 32px; line-height: 32px;">
<button type="button" class="ant-btn ant-btn-default"><span>loading more</span></button>
</div>
</div>
`;
exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
<div class="ant-list ant-list-split ant-list-grid">
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-row" style="margin-left: -8px; margin-right: -8px;">
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 1</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 2</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 3</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 4</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 5</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
<div class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8" style="padding-left: 8px; padding-right: 8px;">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">
<div class="ant-card ant-card-bordered">
<div class="ant-card-head">
<div class="ant-card-head-wrapper">
<div class="ant-card-head-title">Title 6</div>
</div>
</div>
<div class="ant-card-body">Card content</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/list/demo/simple.md correctly 1`] = `
<div>
<h3 style="margin-bottom: 16px;">Default Size</h3>
<div class="ant-list ant-list-split ant-list-bordered ant-list-something-after-last-item">
<div class="ant-list-header">
<div>Header</div>
</div>
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Racing car sprays burning fuel into crowd.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Japanese princess to wed commoner.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Australian walks 100km after outback crash.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Man charged over missing wedding girl.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Los Angeles battles huge wildfires.</div>
</div>
</div>
</div>
<div class="ant-list-footer">
<div>Footer</div>
</div>
</div>
<h3 style="margin: 16px 0px;">Small Size</h3>
<div class="ant-list ant-list-sm ant-list-split ant-list-bordered ant-list-something-after-last-item">
<div class="ant-list-header">
<div>Header</div>
</div>
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Racing car sprays burning fuel into crowd.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Japanese princess to wed commoner.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Australian walks 100km after outback crash.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Man charged over missing wedding girl.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Los Angeles battles huge wildfires.</div>
</div>
</div>
</div>
<div class="ant-list-footer">
<div>Footer</div>
</div>
</div>
<h3 style="margin: 16px 0px;">Large Size</h3>
<div class="ant-list ant-list-lg ant-list-split ant-list-bordered ant-list-something-after-last-item">
<div class="ant-list-header">
<div>Header</div>
</div>
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Racing car sprays burning fuel into crowd.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Japanese princess to wed commoner.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Australian walks 100km after outback crash.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Man charged over missing wedding girl.</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-content ant-list-item-content-single">Los Angeles battles huge wildfires.</div>
</div>
</div>
</div>
<div class="ant-list-footer">
<div>Footer</div>
</div>
</div>
</div>
`;
exports[`renders ./components/list/demo/vertical.md correctly 1`] = `
<div class="ant-list ant-list-vertical ant-list-lg ant-list-split ant-list-something-after-last-item">
<div class="ant-spin-nested-loading">
<div class="ant-spin-container">
<div class="ant-list-item">
<div class="ant-list-item-extra-wrap">
<div class="ant-list-item-main">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">ant design part 0</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team.</div>
</div>
</div>
<div class="ant-list-item-content">
We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.
</div>
<ul class="ant-list-item-action">
<li><span><i class="anticon anticon-star-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-like-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-message-o" style="margin-right: 8px;"></i>
2
</span></li>
</ul>
</div>
<div class="ant-list-item-extra">
<img width="272" alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png">
</div>
</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-extra-wrap">
<div class="ant-list-item-main">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">ant design part 1</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team.</div>
</div>
</div>
<div class="ant-list-item-content">
We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.
</div>
<ul class="ant-list-item-action">
<li><span><i class="anticon anticon-star-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-like-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-message-o" style="margin-right: 8px;"></i>
2
</span></li>
</ul>
</div>
<div class="ant-list-item-extra">
<img width="272" alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png">
</div>
</div>
</div>
<div class="ant-list-item">
<div class="ant-list-item-extra-wrap">
<div class="ant-list-item-main">
<div class="ant-list-item-meta">
<div class="ant-list-item-meta-avatar"><span class="ant-avatar ant-avatar-image ant-avatar-circle"><img src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"></span></div>
<div class="ant-list-item-meta-content">
<h4 class="ant-list-item-meta-title">
<a href="https://vuecomponent.github.io/ant-design/">ant design part 2</a>
</h4>
<div class="ant-list-item-meta-description">Ant Design, a design language for background applications, is refined by Ant UED Team.</div>
</div>
</div>
<div class="ant-list-item-content">
We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.
</div>
<ul class="ant-list-item-action">
<li><span><i class="anticon anticon-star-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-like-o" style="margin-right: 8px;"></i>
156
</span><em class="ant-list-item-action-split"></em></li>
<li><span><i class="anticon anticon-message-o" style="margin-right: 8px;"></i>
2
</span></li>
</ul>
</div>
<div class="ant-list-item-extra">
<img width="272" alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png">
</div>
</div>
</div>
</div>
</div>
<div class="ant-list-pagination">
<ul unselectable="unselectable" class="ant-pagination">
<li title="Previous Page" aria-disabled="true" class="ant-pagination-disabled ant-pagination-prev">
<a class="ant-pagination-item-link"></a>
</li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active">
<a>1</a>
</li>
<li title="2" tabindex="0" class="ant-pagination-item ant-pagination-item-2">
<a>2</a>
</li>
<li title="3" tabindex="0" class="ant-pagination-item ant-pagination-item-3">
<a>3</a>
</li>
<li title="4" tabindex="0" class="ant-pagination-item ant-pagination-item-4">
<a>4</a>
</li>
<li title="5" tabindex="0" class="ant-pagination-item ant-pagination-item-5">
<a>5</a>
</li>
<li title="6" tabindex="0" class="ant-pagination-item ant-pagination-item-6">
<a>6</a>
</li>
<li title="7" tabindex="0" class="ant-pagination-item ant-pagination-item-7">
<a>7</a>
</li>
<li title="8" tabindex="0" class="ant-pagination-item ant-pagination-item-8">
<a>8</a>
</li>
<li title="Next Page" tabindex="0" class=" ant-pagination-next">
<a class="ant-pagination-item-link"></a>
</li>
<!---->
</ul>
</div>
</div>
`;

View File

@ -0,0 +1,3 @@
import demoTest from '../../../tests/shared/demoTest'
demoTest('list')

View File

@ -0,0 +1,53 @@
<cn>
#### 基础列表
基础列表。
</cn>
<us>
#### Basic list
Basic list.
</us>
```html
<template>
<a-list
itemLayout="horizontal"
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-list-item-meta
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
>
<a slot="title" href="https://vuecomponent.github.io/ant-design/">{{item.title}}</a>
<a-avatar slot="avatar" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
</a-list-item-meta>
</a-list-item>
</a-list>
</template>
<script>
const data = [
{
title: 'Ant Design Title 1',
},
{
title: 'Ant Design Title 2',
},
{
title: 'Ant Design Title 3',
},
{
title: 'Ant Design Title 4',
},
]
export default {
data () {
return {
data,
}
},
}
</script>
<style>
</style>
```

View File

@ -0,0 +1,48 @@
<cn>
#### 栅格列表
可以通过设置 `List``grid` 属性来实现栅格列表,`column` 可设置期望显示的列数。
</cn>
<us>
#### Grid
Creating a grid list by setting the `grid` property of List
</us>
```html
<template>
<a-list
:grid="{ gutter: 16, column: 4 }"
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-card :title="item.title">Card content</a-card>
</a-list-item>
</a-list>
</template>
<script>
const data = [
{
title: 'Title 1',
},
{
title: 'Title 2',
},
{
title: 'Title 3',
},
{
title: 'Title 4',
},
]
export default {
data () {
return {
data,
}
},
}
</script>
<style>
</style>
```

View File

@ -0,0 +1,57 @@
<script>
import Basic from './basic'
import Grid from './grid'
import InfiniteLoad from './infinite-load'
import InfiniteVirtualizedLoad from './infinite-virtualized-load'
import Loadmore from './loadmore'
import Resposive from './resposive'
import Simple from './simple'
import Vertical from './vertical'
import CN from '../index.zh-CN.md'
import US from '../index.en-US.md'
const md = {
cn: `# 列表
通用列表
## 何时使用
最基础的列表展示可承载文字列表图片段落常用于后台数据展示页面
## 代码演示`,
us: `# List
Simple List.
## When To Use
A list can be used to display content related to a single subject. The content can consist of multiple elements of varying type and size.
## Examples
`,
}
export default {
category: 'Components',
type: 'Data Display',
title: 'List',
subtitle: '列表',
cols: 1,
render () {
return (
<div>
<md cn={md.cn} us={md.us}/>
<Basic />
<Grid />
<Loadmore />
<Resposive />
<Simple />
<Vertical />
<InfiniteLoad />
<InfiniteVirtualizedLoad />
<api>
<template slot='cn'>
<CN/>
</template>
<US/>
</api>
</div>
)
},
}
</script>

View File

@ -0,0 +1,95 @@
<cn>
#### 滚动加载
结合 [vue-infinite-scroll](https://github.com/ElemeFE/vue-infinite-scroll) 实现滚动自动加载列表。
</cn>
<us>
#### Scrolling loaded
The example of infinite load with [vue-infinite-scroll](https://github.com/ElemeFE/vue-infinite-scroll).
</us>
```html
<template>
<div
class="demo-infinite-container"
v-infinite-scroll="handleInfiniteOnLoad"
:infinite-scroll-disabled="busy"
:infinite-scroll-distance="10"
>
<a-list
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-list-item-meta :description="item.email">
<a slot="title" :href="item.href">{{item.name.last}}</a>
<a-avatar slot="avatar" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
</a-list-item-meta>
<div>Content</div>
</a-list-item>
<a-spin v-if="loading && !busy" class="demo-loading" />
</a-list>
</div>
</template>
<script>
import reqwest from 'reqwest'
import infiniteScroll from 'vue-infinite-scroll'
const fakeDataUrl = 'https://randomuser.me/api/?results=5&inc=name,gender,email,nat&noinfo'
export default {
directives: { infiniteScroll },
data () {
return {
data: [],
loading: false,
busy: false,
}
},
mounted () {
this.getData((res) => {
this.data = res.results
})
},
methods: {
getData (callback) {
reqwest({
url: fakeDataUrl,
type: 'json',
method: 'get',
contentType: 'application/json',
success: (res) => {
callback(res)
},
})
},
handleInfiniteOnLoad () {
const data = this.data
this.loading = true
if (data.length > 14) {
this.$message.warning('Infinite List loaded all')
this.busy = true
this.loading = false
return
}
this.getData((res) => {
this.data = data.concat(res.results)
this.loading = false
})
},
},
}
</script>
<style>
.demo-infinite-container {
border: 1px solid #e8e8e8;
border-radius: 4px;
overflow: auto;
padding: 8px 24px;
height: 300px;
}
.demo-loading {
position: absolute;
bottom: 40px;
width: 100%;
text-align: center;
}
</style>
```

View File

@ -0,0 +1,95 @@
<cn>
#### 滚动加载无限长列表
结合 [vue-virtual-scroller](https://github.com/Akryum/vue-virtual-scroller) 实现滚动加载无限长列表,带有虚拟化([virtualization](https://blog.jscrambler.com/optimizing-react-rendering-through-virtualization/))功能,能够提高数据量大时候长列表的性能。
可以结合 [vue-infinite-scroll](https://github.com/ElemeFE/vue-infinite-scroll) 实现滚动自动加载无限长列表。
`virtualized` 是在大数据列表中应用的一种技术,主要是为了减少不可见区域不必要的渲染从而提高性能,特别是数据量在成千上万条效果尤为明显。
</cn>
<us>
#### Infinite & virtualized
An example of infinite list & virtualized loading using [vue-virtual-scroller](https://github.com/Akryum/vue-virtual-scroller).
`Virtualized` rendering is a technique to mount big sets of data. It reduces the amount of rendered DOM nodes by tracking and hiding whatever isn't currently visible.
</us>
```html
<template>
<a-list>
<virtual-scroller
style="height: 400px"
:items="data"
item-height="73"
v-infinite-scroll="handleInfiniteOnLoad"
:infinite-scroll-disabled="busy"
:infinite-scroll-distance="10"
>
<a-list-item slot-scope="{item}">
<a-list-item-meta :description="item.email">
<a slot="title" :href="item.href">{{item.name.last}}</a>
<a-avatar slot="avatar" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
</a-list-item-meta>
<div>Content {{item.index}}</div>
</a-list-item>
</virtual-scroller>
<a-spin v-if="loading" class="demo-loading" />
</a-list>
</template>
<script>
import reqwest from 'reqwest'
import infiniteScroll from 'vue-infinite-scroll'
import { VirtualScroller } from 'vue-virtual-scroller'
const fakeDataUrl = 'https://randomuser.me/api/?results=10&inc=name,gender,email,nat&noinfo'
export default {
directives: { infiniteScroll },
data () {
return {
data: [],
loading: false,
busy: false,
}
},
mounted () {
this.getData((res) => {
this.data = res.results.map((item, index) => ({ ...item, index }))
})
},
methods: {
getData (callback) {
reqwest({
url: fakeDataUrl,
type: 'json',
method: 'get',
contentType: 'application/json',
success: (res) => {
callback(res)
},
})
},
handleInfiniteOnLoad () {
const data = this.data
this.loading = true
if (data.length > 100) {
this.$message.warning('Infinite List loaded all')
this.busy = true
this.loading = false
return
}
this.getData((res) => {
this.data = data.concat(res.results).map((item, index) => ({ ...item, index }))
this.loading = false
})
},
},
components: {
'virtual-scroller': VirtualScroller,
},
}
</script>
<style>
.demo-loading {
position: absolute;
bottom: 40px;
width: 100%;
text-align: center;
}
</style>
```

View File

@ -0,0 +1,86 @@
<cn>
#### 加载更多
可通过 `loadMore` 属性实现加载更多功能。
</cn>
<us>
#### Load more
Load more list with `loadMore` property.
</us>
```html
<template>
<a-list
class="demo-loadmore-list"
:loading="loading"
itemLayout="horizontal"
:dataSource="data"
>
<div v-if="showLoadingMore" slot="loadMore" :style="{ textAlign: 'center', marginTop: '12px', height: '32px', lineHeight: '32px' }">
<a-spin v-if="loadingMore" />
<a-button v-else @click="onLoadMore">loading more</a-button>
</div>
<a-list-item slot="renderItem" slot-scope="item, index">
<a slot="actions">edit</a>
<a slot="actions">more</a>
<a-list-item-meta
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
>
<a slot="title" href="https://vuecomponent.github.io/ant-design/">{{item.name.last}}</a>
<a-avatar slot="avatar" src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
</a-list-item-meta>
<div>content</div>
</a-list-item>
</a-list>
</template>
<script>
import reqwest from 'reqwest'
const fakeDataUrl = 'https://randomuser.me/api/?results=5&inc=name,gender,email,nat&noinfo'
export default {
data () {
return {
loading: true,
loadingMore: false,
showLoadingMore: true,
data: [],
}
},
mounted () {
this.getData((res) => {
this.loading = false
this.data = res.results
})
},
methods: {
getData (callback) {
reqwest({
url: fakeDataUrl,
type: 'json',
method: 'get',
contentType: 'application/json',
success: (res) => {
callback(res)
},
})
},
onLoadMore () {
this.loadingMore = true
this.getData((res) => {
this.data = this.data.concat(res.results)
this.loadingMore = false
this.$nextTick(() => {
window.dispatchEvent(new Event('resize'))
})
})
},
},
}
</script>
<style>
.demo-loadmore-list {
min-height: 350px;
}
</style>
```

View File

@ -0,0 +1,55 @@
<cn>
#### 响应式的栅格列表
响应式的栅格列表。尺寸与 [Layout Grid](https://vuecomponent.github.io/ant-design/components/grid-cn/#Col) 保持一致。
</cn>
<us>
#### Responsive grid list
Responsive grid list. The size property is as same as [Layout Grid](https://vuecomponent.github.io/ant-design/components/grid/#Col).
</us>
```html
<template>
<a-list
:grid="{ gutter: 16, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: 3 }"
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-card :title="item.title">Card content</a-card>
</a-list-item>
</a-list>
</template>
<script>
const data = [
{
title: 'Title 1',
},
{
title: 'Title 2',
},
{
title: 'Title 3',
},
{
title: 'Title 4',
},
{
title: 'Title 5',
},
{
title: 'Title 6',
},
]
export default {
data () {
return {
data,
}
},
}
</script>
<style>
</style>
```

View File

@ -0,0 +1,69 @@
<cn>
#### 简单列表
列表拥有大、中、小三种尺寸。
通过设置 `size``large` `small` 分别把按钮设为大、小尺寸。若不设置 `size`,则尺寸为中。
可通过设置 `header``footer`,来自定义列表头部和尾部。
</cn>
<us>
#### Simple list
Ant Design supports a default list size as well as a large and small size.
If a large or small list is desired, set the size property to either large or small respectively. Omit the size property for a list with the default size.
Customizing the header and footer of list by setting `header` and `footer` property.
</us>
```html
<template>
<div>
<h3 :style="{ marginBottom: '16px' }">Default Size</h3>
<a-list
bordered
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">{{item}}</a-list-item>
<div slot="header">Header</div>
<div slot="footer">Footer</div>
</a-list>
<h3 :style="{ margin: '16px 0' }">Small Size</h3>
<a-list
size="small"
bordered
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">{{item}}</a-list-item>
<div slot="header">Header</div>
<div slot="footer">Footer</div>
</a-list>
<h3 :style="{ margin: '16px 0' }">Large Size</h3>
<a-list
size="large"
bordered
:dataSource="data"
>
<a-list-item slot="renderItem" slot-scope="item, index">{{item}}</a-list-item>
<div slot="header">Header</div>
<div slot="footer">Footer</div>
</a-list>
</div>
</template>
<script>
const data = [
'Racing car sprays burning fuel into crowd.',
'Japanese princess to wed commoner.',
'Australian walks 100km after outback crash.',
'Man charged over missing wedding girl.',
'Los Angeles battles huge wildfires.',
]
export default {
data () {
return {
data,
}
},
}
</script>
<style>
</style>
```

View File

@ -0,0 +1,73 @@
<cn>
#### 竖排列表样式
通过设置 `itemLayout` 属性为 `vertical` 可实现竖排列表样式。
</cn>
<us>
#### Vertical
Setting `itemLayout` property with `vertical` to create a vertical list.
</us>
```html
<template>
<a-list
itemLayout="vertical"
size="large"
:pagination="pagination"
:dataSource="listData"
>
<a-list-item slot="renderItem" slot-scope="item, index" key="item.title">
<template slot="actions" v-for="{type, text} in actions">
<span :key="type">
<a-icon :type="type" style="margin-right: 8px" />
{{text}}
</span>
</template>
<img slot="extra" width="272" alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png" />
<a-list-item-meta
:description="item.description"
>
<a slot="title" :href="item.href">{{item.title}}</a>
<a-avatar slot="avatar" :src="item.avatar" />
</a-list-item-meta>
{{item.content}}
</a-list-item>
</a-list>
</template>
<script>
const listData = []
for (let i = 0; i < 23; i++) {
listData.push({
href: 'https://vuecomponent.github.io/ant-design/',
title: `ant design part ${i}`,
avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
description: 'Ant Design, a design language for background applications, is refined by Ant UED Team.',
content: 'We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.',
})
}
const pagination = {
onChange: (page) => {
console.log(page)
},
pageSize: 3,
}
export default {
data () {
return {
listData,
pagination,
actions: [
{ type: 'star-o', text: '156' },
{ type: 'like-o', text: '156' },
{ type: 'message-o', text: '2' },
],
}
},
}
</script>
<style>
</style>
```

View File

@ -0,0 +1,46 @@
## API
### List
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| bordered | Toggles rendering of the border around the list | boolean | false |
| footer | List footer renderer | string\|slot | - |
| grid | The grid type of list. You can set grid to something like {gutter: 16, column: 4} | object | - |
| header | List header renderer | string\|slot | - |
| itemLayout | The layout of list, default is `horizontal`, If a vertical list is desired, set the itemLayout property to `vertical` | string | - |
| loading | Shows a loading indicator while the contents of the list are being fetched | boolean\|[object](https://vuecomponent.github.io/ant-design/components/spin/#API) | false |
| loadMore | Shows a load more content | string\|slot | - |
| pagination | Pagination [config](https://vuecomponent.github.io/ant-design/components/pagination/#API), hide it by setting it to false | boolean \| object | false |
| split | Toggles rendering of the split under the list item | boolean | true |
| renderItem | Custom item renderer, slot="renderItem" and slot-scope="item, index" | (item, index) => vNode | | - |
### List grid props
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| column | column of grid | number | - |
| gutter | spacing between grid | number | 0 |
| size | Size of list | `default` \| `middle` \| `small` | `default` |
| xs | `<576px` column of grid | number | - |
| sm | `≥576px` column of grid | number | - |
| md | `≥768px` column of grid | number | - |
| lg | `≥992px` column of grid | number | - |
| xl | `≥1200px` column of grid | number | - |
| xxl | `≥1600px` column of grid | number | - |
### List.Item
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| actions | The actions content of list item. If `itemLayout` is `vertical`, shows the content on bottom, otherwise shows content on the far right. | Array\<vNode>\|slot | - |
| extra | The extra content of list item. If `itemLayout` is `vertical`, shows the content on right, otherwise shows content on the far right. | string\|slot | - |
### List.Item.Meta
| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| avatar | The avatar of list item | slot | - |
| description | The description of list item | string\|slot | - |
| title | The title of list item | string\|slot | - |

249
components/list/index.jsx Normal file
View File

@ -0,0 +1,249 @@
import PropTypes from '../_util/vue-types'
import classNames from 'classnames'
import omit from 'omit.js'
import { SpinProps } from '../spin'
import LocaleReceiver from '../locale-provider/LocaleReceiver'
import defaultLocale from '../locale-provider/default'
import Spin from '../spin'
import Pagination from '../pagination'
import { Row } from '../grid'
import Item from './Item'
import { initDefaultProps, getComponentFromProp } from '../_util/props-util'
import { cloneElement } from '../_util/vnode'
export { ListItemProps, ListItemMetaProps } from './Item'
export const ColumnCount = ['', 1, 2, 3, 4, 6, 8, 12, 24]
export const ColumnType = ['gutter', 'column', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl']
export const ListGridType = {
gutter: PropTypes.number,
column: PropTypes.oneOf(ColumnCount),
xs: PropTypes.oneOf(ColumnCount),
sm: PropTypes.oneOf(ColumnCount),
md: PropTypes.oneOf(ColumnCount),
lg: PropTypes.oneOf(ColumnCount),
xl: PropTypes.oneOf(ColumnCount),
xxl: PropTypes.oneOf(ColumnCount),
}
export const ListSize = ['small', 'default', 'large']
export const ListProps = () => ({
bordered: PropTypes.bool,
dataSource: PropTypes.any,
extra: PropTypes.any,
grid: PropTypes.shape(ListGridType).loose,
itemLayout: PropTypes.string,
loading: PropTypes.oneOfType([PropTypes.bool, SpinProps()]),
loadMore: PropTypes.any,
pagination: PropTypes.any,
prefixCls: PropTypes.string,
rowKey: PropTypes.any,
renderItem: PropTypes.any,
size: PropTypes.oneOf(ListSize),
split: PropTypes.bool,
header: PropTypes.any,
footer: PropTypes.any,
locale: PropTypes.object,
})
export default {
Item,
name: 'AList',
props: initDefaultProps(ListProps(), {
dataSource: [],
prefixCls: 'ant-list',
bordered: false,
split: true,
loading: false,
pagination: false,
}),
provide () {
return {
listContext: this,
}
},
data () {
this.keys = []
this.defaultPaginationProps = {
current: 1,
pageSize: 10,
onChange: (page, pageSize) => {
const { pagination } = this
this.paginationCurrent = page
if (pagination && pagination.onChange) {
pagination.onChange(page, pageSize)
}
},
total: 0,
}
return {
paginationCurrent: 1,
}
},
methods: {
renderItem2 (item, index) {
const { dataSource, $scopedSlots, rowKey } = this
let key
const renderItem = this.renderItem || $scopedSlots.renderItem
if (typeof rowKey === 'function') {
key = rowKey(dataSource[index])
} else if (typeof rowKey === 'string') {
key = dataSource[rowKey]
} else {
key = dataSource.key
}
if (!key) {
key = `list-item-${index}`
}
this.keys[index] = key
return renderItem(item, index)
},
isSomethingAfterLastTtem () {
const { pagination } = this
const loadMore = getComponentFromProp(this, 'loadMore')
const footer = getComponentFromProp(this, 'footer')
return !!(loadMore || pagination || footer)
},
renderEmpty (contextLocale) {
const locale = { ...contextLocale, ...this.locale }
return <div class={`${this.prefixCls}-empty-text`}>{locale.emptyText}</div>
},
},
render () {
const {
bordered,
split,
itemLayout,
pagination,
prefixCls,
grid,
dataSource,
size,
loading,
$listeners,
$slots,
paginationCurrent,
} = this
const loadMore = getComponentFromProp(this, 'loadMore')
const footer = getComponentFromProp(this, 'footer')
const header = getComponentFromProp(this, 'header')
const children = $slots.default || []
let loadingProp = loading
if (typeof loadingProp === 'boolean') {
loadingProp = {
spinning: loadingProp,
}
}
const isLoading = (loadingProp && loadingProp.spinning)
// large => lg
// small => sm
let sizeCls = ''
switch (size) {
case 'large':
sizeCls = 'lg'
break
case 'small':
sizeCls = 'sm'
break
default:
break
}
const classString = classNames(prefixCls, {
[`${prefixCls}-vertical`]: itemLayout === 'vertical',
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-split`]: split,
[`${prefixCls}-bordered`]: bordered,
[`${prefixCls}-loading`]: isLoading,
[`${prefixCls}-grid`]: grid,
[`${prefixCls}-something-after-last-item`]: this.isSomethingAfterLastTtem(),
})
const paginationProps = {
...this.defaultPaginationProps,
total: dataSource.length,
current: paginationCurrent,
...pagination || {},
}
const largestPage = Math.ceil(
paginationProps.total / paginationProps.pageSize,
)
if (paginationProps.current > largestPage) {
paginationProps.current = largestPage
}
const { class: cls, style, onShowSizeChange = () => {}, ...restProps } = paginationProps
const paginationContent = pagination ? (
<div class={`${prefixCls}-pagination`}>
<Pagination
{...{
props: omit(restProps, ['onChange']),
class: cls, style,
on: { change: this.defaultPaginationProps.onChange, showSizeChange: onShowSizeChange },
}}
/>
</div>
) : null
let splitDataSource = [...dataSource]
if (pagination) {
if (
dataSource.length >
(paginationProps.current - 1) * paginationProps.pageSize
) {
splitDataSource = [...dataSource].splice(
(paginationProps.current - 1) * paginationProps.pageSize,
paginationProps.pageSize,
)
}
}
let childrenContent
childrenContent = isLoading && (<div style={{ minHeight: 53 }} />)
if (splitDataSource.length > 0) {
const items = splitDataSource.map((item, index) => this.renderItem2(item, index))
const childrenList = items.map((child, index) => cloneElement(child, {
key: this.keys[index],
}),
)
childrenContent = grid ? (
<Row gutter={grid.gutter}>{childrenList}</Row>
) : childrenList
} else if (!children && !isLoading) {
childrenContent = (
<LocaleReceiver
componentName='Table'
defaultLocale={defaultLocale.Table}
scopedSlots={
{ default: this.renderEmpty }
}
/>
)
}
const paginationPosition = paginationProps.position || 'bottom'
return (
<div class={classString} {...{ on: $listeners }}>
{(paginationPosition === 'top' || paginationPosition === 'both') && paginationContent}
{header && <div class={`${prefixCls}-header`}>{header}</div>}
<Spin {...{ props: loadingProp }}>
{childrenContent}
{children}
</Spin>
{footer && <div class={`${prefixCls}-footer`}>{footer}</div>}
{loadMore || (paginationPosition === 'bottom' || paginationPosition === 'both') && paginationContent}
</div>
)
},
}

View File

@ -0,0 +1,46 @@
## API
### List
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| bordered | 是否展示边框 | boolean | false |
| footer | 列表底部 | string\|slot | - |
| grid | 列表栅格配置 | object | - |
| header | 列表头部 | string\|slot | - |
| itemLayout | 设置 `List.Item` 布局, 设置成 `vertical` 则竖直样式显示, 默认横排 | string | - |
| loading | 当卡片内容还在加载中时,可以用 `loading` 展示一个占位 | boolean\|[object](https://vuecomponent.github.io/ant-design/components/spin-cn/#API) | false |
| loadMore | 加载更多 | string\|slot | - |
| pagination | 对应的 `pagination` [配置]((https://vuecomponent.github.io/ant-design/components/pagination-cn/#API)), 设置 `false` 不显示 | boolean\|object | false |
| size | list 的尺寸 | `default` \| `middle` \| `small` | `default` |
| split | 是否展示分割线 | boolean | true |
| renderItem | 自定义`Item`函数也可使用slot="renderItem" 和 slot-scope="item, index" | (item, index) => vNode | | - |
### List grid props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| column | 列数 | number | - |
| gutter | 栅格间隔 | number | 0 |
| xs | `<576px` 展示的列数 | number | - |
| sm | `≥576px` 展示的列数 | number | - |
| md | `≥768px` 展示的列数 | number | - |
| lg | `≥992px` 展示的列数 | number | - |
| xl | `≥1200px` 展示的列数 | number | - |
| xxl | `≥1600px` 展示的列数 | number | - |
### List.Item
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| actions | 列表操作组,根据 `itemLayout` 的不同, 位置在卡片底部或者最右侧 | Array\<vNode>/|slot | - |
| extra | 额外内容, 通常用在 `itemLayout``vertical` 的情况下, 展示右侧内容; `horizontal` 展示在列表元素最右侧 | string\|slot | - |
### List.Item.Meta
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| avatar | 列表元素的图标 | slot | - |
| description | 列表元素的描述内容 | string\|slot | - |
| title | 列表元素的标题 | string\|slot | - |

View File

@ -0,0 +1,41 @@
.@{list-prefix-cls}-bordered {
border-radius: @border-radius-base;
border: 1px solid @border-color-base;
.@{list-prefix-cls}-header {
padding-left: 24px;
padding-right: 24px;
}
.@{list-prefix-cls}-footer {
padding-left: 24px;
padding-right: 24px;
}
.@{list-prefix-cls}-item {
border-bottom: 1px solid @border-color-split;
padding-left: 24px;
padding-right: 24px;
}
.@{list-prefix-cls}-pagination {
margin: 16px 24px;
}
&.@{list-prefix-cls}-sm {
.@{list-prefix-cls}-item {
padding-left: 16px;
padding-right: 16px;
}
.@{list-prefix-cls}-header,
.@{list-prefix-cls}-footer {
padding: 8px 16px;
}
}
&.@{list-prefix-cls}-lg {
.@{list-prefix-cls}-header,
.@{list-prefix-cls}-footer {
padding: 16px 24px;
}
}
}

View File

@ -0,0 +1,7 @@
import '../../style/index.less'
import './index.less'
// style dependencies
import '../../spin/style'
import '../../pagination/style'
import '../../grid/style'

View File

@ -0,0 +1,207 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@list-prefix-cls: ~"@{ant-prefix}-list";
.@{list-prefix-cls} {
.reset-component;
position: relative;
* {
outline: none;
}
&-pagination {
margin-top: 24px;
text-align: right;
}
&-more {
margin-top: 12px;
text-align: center;
button {
padding-left: 32px;
padding-right: 32px;
}
}
&-spin {
text-align: center;
min-height: 40px;
}
&-empty-text {
color: @text-color-secondary;
font-size: @font-size-base;
padding: 16px;
text-align: center;
}
&-item {
align-items: center;
display: flex;
padding-top: 12px;
padding-bottom: 12px;
&-meta {
align-items: flex-start;
display: flex;
flex: 1;
font-size: 0;
&-avatar {
margin-right: 16px;
}
&-content {
flex: 1 0;
}
&-title {
color: @text-color;
margin-bottom: 4px;
font-size: @font-size-base;
line-height: 22px;
> a {
color: @text-color;
transition: all .3s;
&:hover {
color: @primary-color;
}
}
}
&-description {
color: @text-color-secondary;
font-size: @font-size-base;
line-height: 22px;
}
}
&-content {
display: flex;
flex: 1;
justify-content: flex-end;
}
&-content-single {
justify-content: flex-start;
}
&-action {
font-size: 0;
flex: 0 0 auto;
margin-left: 48px;
padding: 0;
list-style: none;
& > li {
display: inline-block;
color: @text-color-secondary;
cursor: pointer;
padding: 0 8px;
position: relative;
font-size: @font-size-base;
line-height: 22px;
text-align: center;
}
& > li:first-child {
padding-left: 0;
}
&-split {
background-color: @border-color-split;
margin-top: -7px;
position: absolute;
top: 50%;
right: 0;
width: 1px;
height: 14px;
}
}
&-main {
display: flex;
flex: 1;
}
}
&-header,
&-footer {
padding-top: 12px;
padding-bottom: 12px;
}
&-empty {
color: @text-color-secondary;
padding: 16px 0;
font-size: 12px;
text-align: center;
}
&-split &-item {
border-bottom: 1px solid @border-color-split;
&:last-child {
border-bottom: none;
}
}
&-split &-header {
border-bottom: 1px solid @border-color-split;
}
&-loading &-spin-nested-loading {
min-height: 32px;
}
&-something-after-last-item &-item:last-child {
border-bottom: 1px solid @border-color-split;
}
&-lg &-item {
padding-top: 16px;
padding-bottom: 16px;
}
&-sm &-item {
padding-top: 8px;
padding-bottom: 8px;
}
&-vertical &-item {
display: block;
&-extra-wrap {
display: flex;
}
&-main {
display: block;
flex: 1;
}
&-extra {
margin-left: 58px;
}
&-meta {
margin-bottom: 16px;
&-avatar {
display: none;
}
&-title {
color: @heading-color;
margin-bottom: 12px;
font-size: @font-size-lg;
line-height: 24px;
}
}
&-content {
display: block;
color: @text-color;
font-size: @font-size-base;
margin-bottom: 16px;
}
&-action {
margin-left: auto;
> li {
padding: 0 16px;
&:first-child {
padding-left: 0;
}
}
}
}
&-grid &-item {
border-bottom: none;
padding-top: 0;
padding-bottom: 0;
margin-bottom: 20px;
&-content {
display: block;
}
}
}
@import './bordered';
@import './responsive';

View File

@ -0,0 +1,42 @@
@media screen and (max-width: @screen-md) {
.@{list-prefix-cls} {
&-item {
&-action {
margin-left: 24px;
}
}
}
.@{list-prefix-cls}-vertical {
.@{list-prefix-cls}-item {
&-extra {
margin-left: 24px;
}
}
}
}
@media screen and (max-width: @screen-xs) {
.@{list-prefix-cls} {
&-item {
flex-wrap: wrap;
&-action {
margin-left: 12px;
}
}
}
.@{list-prefix-cls}-vertical {
.@{list-prefix-cls}-item {
&-extra-wrap {
flex-wrap: wrap-reverse;
}
&-main {
min-width: 220px;
}
&-extra {
margin-left: 0;
}
}
}
}

View File

@ -45,3 +45,4 @@ import './upload/style'
import './layout/style'
import './form/style'
import './anchor/style'
import './list/style'

View File

@ -24,7 +24,7 @@ import {
Input,
InputNumber,
Layout,
// List,
List,
LocaleProvider,
message,
Menu,
@ -100,7 +100,9 @@ Vue.component(Layout.Header.name, Layout.Header)
Vue.component(Layout.Footer.name, Layout.Footer)
Vue.component(Layout.Sider.name, Layout.Sider)
Vue.component(Layout.Content.name, Layout.Content)
// Vue.component(List.name, List)
Vue.component(List.name, List)
Vue.component(List.Item.name, List.Item)
Vue.component(List.Item.Meta.name, List.Item.Meta)
Vue.component(LocaleProvider.name, LocaleProvider)
Vue.component(Menu.name, Menu)
Vue.component(Menu.Item.name, Menu.Item)

View File

@ -46,3 +46,4 @@ export { default as tree } from 'antd/tree/demo/index.vue'
export { default as layout } from 'antd/layout/demo/index.vue'
export { default as form } from 'antd/form/demo/index.vue'
export { default as anchor } from 'antd/anchor/demo/index.vue'
export { default as list } from 'antd/list/demo/index.vue'

View File

@ -29,6 +29,7 @@ Array [
"Input",
"InputNumber",
"Layout",
"List",
"LocaleProvider",
"Menu",
"Modal",