From 38d78ae2fb0828b74d841845d1cff1060dba92fa Mon Sep 17 00:00:00 2001 From: Andy <869732751@qq.com> Date: Tue, 30 Jun 2020 22:37:37 +0800 Subject: [PATCH 1/3] feat(list): update to vue3 --- components/list/Item.jsx | 89 +++++++++---------- .../__snapshots__/empty.test.js.snap | 6 ++ components/list/index.jsx | 87 +++++++++--------- 3 files changed, 95 insertions(+), 87 deletions(-) diff --git a/components/list/Item.jsx b/components/list/Item.jsx index 20759106f7..8c590d5078 100644 --- a/components/list/Item.jsx +++ b/components/list/Item.jsx @@ -1,15 +1,11 @@ import PropTypes from '../_util/vue-types'; import classNames from 'classnames'; -import { - getComponentFromProp, - isStringElement, - getListeners, - isEmptyElement, -} from '../_util/props-util'; +import { getComponent, isStringElement, isEmptyElement, getSlot } from '../_util/props-util'; import { Col } from '../grid'; import { ConfigConsumerProps } from '../config-provider'; import { ListGridType } from './index'; import { cloneElement } from '../_util/vnode'; +import { inject } from 'vue'; export const ListItemProps = { prefixCls: PropTypes.string, @@ -26,34 +22,33 @@ export const ListItemMetaProps = { }; export const Meta = { + props: ListItemMetaProps, + inheritAttributes: false, functional: true, name: 'AListItemMeta', __ANT_LIST_ITEM_META: true, - inject: { - configProvider: { default: () => ConfigConsumerProps }, - }, - render(h, context) { - const { props, slots, listeners, injections } = context; - const slotsMap = slots(); - const getPrefixCls = injections.configProvider.getPrefixCls; - const { prefixCls: customizePrefixCls } = props; - const prefixCls = getPrefixCls('list', customizePrefixCls); - - const avatar = props.avatar || slotsMap.avatar; - const title = props.title || slotsMap.title; - const description = props.description || slotsMap.description; - const content = ( -
- {title &&

{title}

} - {description &&
{description}
} -
- ); - return ( -
- {avatar &&
{avatar}
} - {(title || description) && content} -
- ); + setup(props, { slots, attrs }) { + const configProvider = inject('configProvider', ConfigConsumerProps); + return () => { + const getPrefixCls = configProvider.getPrefixCls; + const { prefixCls: customizePrefixCls } = props; + const prefixCls = getPrefixCls('list', customizePrefixCls); + const avatar = props.avatar || slots.avatar?.(); + const title = props.title || slots.title?.(); + const description = props.description || slots.description?.(); + const content = ( +
+ {title &&

{title}

} + {description &&
{description}
} +
+ ); + return ( +
+ {avatar &&
{avatar}
} + {(title || description) && content} +
+ ); + }; }, }; @@ -62,18 +57,22 @@ function getGrid(grid, t) { } export default { + inheritAttributes: false, name: 'AListItem', Meta, props: ListItemProps, - inject: { - listContext: { default: () => ({}) }, - configProvider: { default: () => ConfigConsumerProps }, + setup() { + const listContext = inject('listContext', {}); + const configProvider = inject('configProvider', ConfigConsumerProps); + return { + listContext, + configProvider, + }; }, methods: { isItemContainsTextNodeAndNotSingular() { - const { $slots } = this; + const children = getSlot(this) || []; let result; - const children = $slots.default || []; children.forEach(element => { if (isStringElement(element) && !isEmptyElement(element)) { result = true; @@ -83,7 +82,7 @@ export default { }, isFlexMode() { - const extra = getComponentFromProp(this, 'extra'); + const extra = getComponent(this, 'extra'); const { itemLayout } = this.listContext; if (itemLayout === 'vertical') { return !!extra; @@ -93,12 +92,12 @@ export default { }, render() { const { grid, itemLayout } = this.listContext; - const { prefixCls: customizePrefixCls, $slots } = this; - const listeners = getListeners(this); + const { prefixCls: customizePrefixCls, $slots, $attrs } = this; + const { class: _className } = $attrs; const getPrefixCls = this.configProvider.getPrefixCls; const prefixCls = getPrefixCls('list', customizePrefixCls); - const extra = getComponentFromProp(this, 'extra'); - const actions = getComponentFromProp(this, 'actions'); + const extra = getComponent(this, 'extra'); + const actions = getComponent(this, 'actions'); const actionsContent = actions && actions.length > 0 && ( ); - + const children = $slots.default && $slots.default(); const Tag = grid ? 'div' : 'li'; const itemChildren = ( @@ -129,7 +128,7 @@ export default { {extra} , ] - : [$slots.default, actionsContent, cloneElement(extra, { key: 'extra' })]} + : [children, actionsContent, cloneElement(extra, { key: 'extra' })]} ); diff --git a/components/list/__tests__/__snapshots__/empty.test.js.snap b/components/list/__tests__/__snapshots__/empty.test.js.snap index 761d8f8635..6c7b86b902 100644 --- a/components/list/__tests__/__snapshots__/empty.test.js.snap +++ b/components/list/__tests__/__snapshots__/empty.test.js.snap @@ -2,7 +2,10 @@ exports[`List renders empty list 1`] = `
+ +
+
@@ -16,9 +19,12 @@ exports[`List renders empty list 1`] = `

No Data

+
+ + `; diff --git a/components/list/index.jsx b/components/list/index.jsx index c85716744d..871b1a26e0 100644 --- a/components/list/index.jsx +++ b/components/list/index.jsx @@ -8,14 +8,9 @@ import Pagination, { PaginationConfig } from '../pagination'; import { Row } from '../grid'; import Item from './Item'; -import { - initDefaultProps, - getComponentFromProp, - filterEmpty, - getListeners, -} from '../_util/props-util'; +import { initDefaultProps, getComponent, getSlot } from '../_util/props-util'; import { cloneElement } from '../_util/vnode'; -import Base from '../base'; +import { provide, inject } from 'vue'; export { ListItemProps, ListItemMetaProps } from './Item'; @@ -56,6 +51,7 @@ export const ListProps = () => ({ }); const List = { + inheritAttributes: false, Item, name: 'AList', props: initDefaultProps(ListProps(), { @@ -65,14 +61,15 @@ const List = { loading: false, pagination: false, }), - provide() { + created() { + provide('listContext', this); + }, + setup() { return { - listContext: this, + configProvider: inject('configProvider', ConfigConsumerProps), }; }, - inject: { - configProvider: { default: () => ConfigConsumerProps }, - }, + data() { this.keys = []; this.defaultPaginationProps = { @@ -107,10 +104,13 @@ const List = { } }; }, - renderItem2(item, index) { - const { $scopedSlots, rowKey } = this; - const renderItem = this.renderItem || $scopedSlots.renderItem; - if (!renderItem) return null; + innerRenderItem(item, index) { + const { + $slots: { renderItem }, + rowKey, + } = this; + const renderer = this.renderItem || renderItem; + if (!renderer) return null; let key; if (typeof rowKey === 'function') { key = rowKey(item); @@ -126,13 +126,13 @@ const List = { this.keys[index] = key; - return renderItem(item, index); + return renderer(item, index); }, isSomethingAfterLastItem() { const { pagination } = this; - const loadMore = getComponentFromProp(this, 'loadMore'); - const footer = getComponentFromProp(this, 'footer'); + const loadMore = getComponent(this, 'loadMore'); + const footer = getComponent(this, 'footer'); return !!(loadMore || pagination || footer); }, @@ -140,7 +140,7 @@ const List = { const { locale } = this; return (
- {(locale && locale.emptyText) || renderEmpty(h, 'List')} + {(locale && locale.emptyText) || renderEmpty('List')}
); }, @@ -157,17 +157,17 @@ const List = { dataSource = [], size, loading, - $slots, paginationCurrent, paginationSize, + $attrs, } = this; const getPrefixCls = this.configProvider.getPrefixCls; const prefixCls = getPrefixCls('list', customizePrefixCls); - const loadMore = getComponentFromProp(this, 'loadMore'); - const footer = getComponentFromProp(this, 'footer'); - const header = getComponentFromProp(this, 'header'); - const children = filterEmpty($slots.default || []); + const loadMore = getComponent(this, 'loadMore'); + const footer = getComponent(this, 'footer'); + const header = getComponent(this, 'header'); + const children = getSlot(this); let loadingProp = loading; if (typeof loadingProp === 'boolean') { loadingProp = { @@ -189,15 +189,19 @@ const List = { 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.isSomethingAfterLastItem(), - }); + 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.isSomethingAfterLastItem(), + }, + $attrs.class, + ); const paginationProps = { ...this.defaultPaginationProps, total: dataSource.length, @@ -239,7 +243,7 @@ const List = { let childrenContent; childrenContent = isLoading &&
; if (splitDataSource.length > 0) { - const items = splitDataSource.map((item, index) => this.renderItem2(item, index)); + const items = splitDataSource.map((item, index) => this.innerRenderItem(item, index)); const childrenList = items.map((child, index) => cloneElement(child, { key: this.keys[index], @@ -258,10 +262,10 @@ const List = { const paginationPosition = paginationProps.position || 'bottom'; return ( -
+
{(paginationPosition === 'top' || paginationPosition === 'both') && paginationContent} {header &&
{header}
} - + {childrenContent} {children} @@ -274,11 +278,10 @@ const List = { }; /* istanbul ignore next */ -List.install = function(Vue) { - Vue.use(Base); - Vue.component(List.name, List); - Vue.component(List.Item.name, List.Item); - Vue.component(List.Item.Meta.name, List.Item.Meta); +List.install = function(app) { + app.component(List.name, List); + app.component(List.Item.name, List.Item); + app.component(List.Item.Meta.name, List.Item.Meta); }; export default List; From 42cb3f13703093f3dc70955762f7f075b9571397 Mon Sep 17 00:00:00 2001 From: Andy <869732751@qq.com> Date: Wed, 8 Jul 2020 20:53:42 +0800 Subject: [PATCH 2/3] feat(list): refactor meta to functional --- components/list/Item.jsx | 55 ++++++++++++++++++--------------------- components/list/index.jsx | 2 +- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/components/list/Item.jsx b/components/list/Item.jsx index 8c590d5078..107496b88c 100644 --- a/components/list/Item.jsx +++ b/components/list/Item.jsx @@ -21,44 +21,41 @@ export const ListItemMetaProps = { title: PropTypes.any, }; -export const Meta = { +export const Meta = (props, { slots, attrs }) => { + const configProvider = inject('configProvider', ConfigConsumerProps); + const getPrefixCls = configProvider.getPrefixCls; + const { prefixCls: customizePrefixCls } = props; + const prefixCls = getPrefixCls('list', customizePrefixCls); + const avatar = props.avatar || slots.avatar?.(); + const title = props.title || slots.title?.(); + const description = props.description || slots.description?.(); + const content = ( +
+ {title &&

{title}

} + {description &&
{description}
} +
+ ); + return ( +
+ {avatar &&
{avatar}
} + {(title || description) && content} +
+ ); +}; + +Object.assign(Meta, { props: ListItemMetaProps, - inheritAttributes: false, - functional: true, - name: 'AListItemMeta', + inheritAttrs: false, __ANT_LIST_ITEM_META: true, - setup(props, { slots, attrs }) { - const configProvider = inject('configProvider', ConfigConsumerProps); - return () => { - const getPrefixCls = configProvider.getPrefixCls; - const { prefixCls: customizePrefixCls } = props; - const prefixCls = getPrefixCls('list', customizePrefixCls); - const avatar = props.avatar || slots.avatar?.(); - const title = props.title || slots.title?.(); - const description = props.description || slots.description?.(); - const content = ( -
- {title &&

{title}

} - {description &&
{description}
} -
- ); - return ( -
- {avatar &&
{avatar}
} - {(title || description) && content} -
- ); - }; - }, -}; +}); function getGrid(grid, t) { return grid[t] && Math.floor(24 / grid[t]); } export default { - inheritAttributes: false, name: 'AListItem', + inheritAttrs: false, Meta, props: ListItemProps, setup() { diff --git a/components/list/index.jsx b/components/list/index.jsx index 871b1a26e0..a36b7328de 100644 --- a/components/list/index.jsx +++ b/components/list/index.jsx @@ -51,7 +51,7 @@ export const ListProps = () => ({ }); const List = { - inheritAttributes: false, + inheritAttrs: false, Item, name: 'AList', props: initDefaultProps(ListProps(), { From a0c2a836e0d5618e3a5d7d4fced2c42663a88d28 Mon Sep 17 00:00:00 2001 From: Andy <869732751@qq.com> Date: Mon, 13 Jul 2020 14:36:12 +0800 Subject: [PATCH 3/3] feat(list): code review --- components/list/Item.jsx | 3 ++- components/list/index.jsx | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/list/Item.jsx b/components/list/Item.jsx index 107496b88c..e252d442af 100644 --- a/components/list/Item.jsx +++ b/components/list/Item.jsx @@ -23,6 +23,7 @@ export const ListItemMetaProps = { export const Meta = (props, { slots, attrs }) => { const configProvider = inject('configProvider', ConfigConsumerProps); + const { style, class: _cls } = attrs; const getPrefixCls = configProvider.getPrefixCls; const { prefixCls: customizePrefixCls } = props; const prefixCls = getPrefixCls('list', customizePrefixCls); @@ -36,7 +37,7 @@ export const Meta = (props, { slots, attrs }) => {
); return ( -
+
{avatar &&
{avatar}
} {(title || description) && content}
diff --git a/components/list/index.jsx b/components/list/index.jsx index a36b7328de..9a8060c0ac 100644 --- a/components/list/index.jsx +++ b/components/list/index.jsx @@ -163,7 +163,7 @@ const List = { } = this; const getPrefixCls = this.configProvider.getPrefixCls; const prefixCls = getPrefixCls('list', customizePrefixCls); - + const { class: _cls, ...restAttrs } = $attrs; const loadMore = getComponent(this, 'loadMore'); const footer = getComponent(this, 'footer'); const header = getComponent(this, 'header'); @@ -209,6 +209,7 @@ const List = { pageSize: paginationSize, ...(pagination || {}), }; + classString; const largestPage = Math.ceil(paginationProps.total / paginationProps.pageSize); if (paginationProps.current > largestPage) { paginationProps.current = largestPage; @@ -262,7 +263,7 @@ const List = { const paginationPosition = paginationProps.position || 'bottom'; return ( -
+
{(paginationPosition === 'top' || paginationPosition === 'both') && paginationContent} {header &&
{header}
}