From 7acf577f56fb1316fe7f6538f41e57a36af097a0 Mon Sep 17 00:00:00 2001 From: tanjinzhou <415800467@qq.com> Date: Thu, 13 May 2021 12:57:42 +0800 Subject: [PATCH] refactor: avatar --- components/_util/hooks/useSize.ts | 26 ++++++ components/avatar/Avatar.tsx | 119 +++++++++++++-------------- components/avatar/Group.tsx | 7 +- components/config-provider/index.tsx | 2 +- 4 files changed, 87 insertions(+), 67 deletions(-) create mode 100644 components/_util/hooks/useSize.ts diff --git a/components/_util/hooks/useSize.ts b/components/_util/hooks/useSize.ts new file mode 100644 index 000000000..4e70469eb --- /dev/null +++ b/components/_util/hooks/useSize.ts @@ -0,0 +1,26 @@ +import { computed, ComputedRef, inject, provide, UnwrapRef } from 'vue'; +import { ConfigProviderProps, defaultConfigProvider, SizeType } from '../../config-provider'; + +const sizeProvider = Symbol('SizeProvider'); + +const useProviderSize = (props: Record): ComputedRef => { + const configProvider = inject>( + 'configProvider', + defaultConfigProvider, + ); + const size = computed(() => props.size || configProvider.componentSize); + provide(sizeProvider, size); + return size; +}; + +const useInjectSize = (): ComputedRef => { + const size: ComputedRef = inject( + sizeProvider, + computed(() => ('default' as unknown) as T), + ); + return size; +}; + +export { useInjectSize, sizeProvider, useProviderSize }; + +export default useProviderSize; diff --git a/components/avatar/Avatar.tsx b/components/avatar/Avatar.tsx index 46b6dbe12..29db24d16 100644 --- a/components/avatar/Avatar.tsx +++ b/components/avatar/Avatar.tsx @@ -7,16 +7,17 @@ import { inject, nextTick, onMounted, - onUpdated, PropType, ref, watch, } from 'vue'; -import { defaultConfigProvider } from '../config-provider'; import { getPropsSlot } from '../_util/props-util'; import PropTypes from '../_util/vue-types'; import useBreakpoint from '../_util/hooks/useBreakpoint'; import { Breakpoint, responsiveArray, ScreenSizeMap } from '../_util/responsiveObserve'; +import useConfigInject from '../_util/hooks/useConfigInject'; +import ResizeObserver from '../vc-resize-observer'; +import { useInjectSize } from '../_util/hooks/useSize'; export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap; @@ -44,6 +45,8 @@ export type AvatarProps = Partial>; const Avatar = defineComponent({ name: 'AAvatar', props: avatarProps, + inheritAttrs: false, + slots: ['icon'], setup(props, { slots, attrs }) { const isImgExist = ref(true); const isMounted = ref(false); @@ -52,12 +55,9 @@ const Avatar = defineComponent({ const avatarChildrenRef = ref(null); const avatarNodeRef = ref(null); - const configProvider = inject('configProvider', defaultConfigProvider); + const { prefixCls } = useConfigInject('avatar', props); - const groupSize = inject( - 'SizeProvider', - computed(() => 'default'), - ); + const groupSize = useInjectSize(); const screens = useBreakpoint(); const responsiveSize = computed(() => { @@ -82,7 +82,7 @@ const Avatar = defineComponent({ return {}; }; - const setScale = () => { + const setScaleParam = () => { if (!avatarChildrenRef.value || !avatarNodeRef.value) { return; } @@ -116,40 +116,35 @@ const Avatar = defineComponent({ }, ); + watch( + () => props.gap, + () => { + nextTick(() => { + setScaleParam(); + }); + }, + ); + onMounted(() => { nextTick(() => { - setScale(); + setScaleParam(); isMounted.value = true; }); }); - onUpdated(() => { - nextTick(() => { - setScale(); - }); - }); - return () => { - const { - prefixCls: customizePrefixCls, - shape, - size: customSize, - src, - alt, - srcset, - draggable, - } = props; + const { shape, size: customSize, src, alt, srcset, draggable } = props; const icon = getPropsSlot(slots, props, 'icon'); - const getPrefixCls = configProvider.getPrefixCls; - const prefixCls = getPrefixCls('avatar', customizePrefixCls); + const pre = prefixCls.value; const size = customSize === 'default' ? groupSize.value : customSize; const classString = { - [prefixCls]: true, - [`${prefixCls}-lg`]: size === 'large', - [`${prefixCls}-sm`]: size === 'small', - [`${prefixCls}-${shape}`]: shape, - [`${prefixCls}-image`]: src && isImgExist.value, - [`${prefixCls}-icon`]: icon, + [`${attrs.class}`]: !!attrs.class, + [pre]: true, + [`${pre}-lg`]: size === 'large', + [`${pre}-sm`]: size === 'small', + [`${pre}-${shape}`]: shape, + [`${pre}-image`]: src && isImgExist.value, + [`${pre}-icon`]: icon, }; const sizeStyle: CSSProperties = @@ -162,9 +157,10 @@ const Avatar = defineComponent({ } : {}; - let children: VueNode = slots.default?.(); + const children: VueNode = slots.default?.(); + let childrenToRender; if (src && isImgExist.value) { - children = ( + childrenToRender = ( ); } else if (icon) { - children = icon; - } else { - const childrenNode = avatarChildrenRef.value; - - if (childrenNode || scale.value !== 1) { - const transformString = `scale(${scale.value}) translateX(-50%)`; - const childrenStyle: CSSProperties = { - msTransform: transformString, - WebkitTransform: transformString, - transform: transformString, - }; - const sizeChildrenStyle = - typeof size === 'number' - ? { - lineHeight: `${size}px`, - } - : {}; - children = ( + childrenToRender = icon; + } else if (isMounted.value || scale.value !== 1) { + const transformString = `scale(${scale.value}) translateX(-50%)`; + const childrenStyle: CSSProperties = { + msTransform: transformString, + WebkitTransform: transformString, + transform: transformString, + }; + const sizeChildrenStyle = + typeof size === 'number' + ? { + lineHeight: `${size}px`, + } + : {}; + childrenToRender = ( + {children} - ); - } else { - children = ( - - {children} - - ); - } + + ); + } else { + childrenToRender = ( + + {children} + + ); } return ( - {children} + {childrenToRender} ); }; diff --git a/components/avatar/Group.tsx b/components/avatar/Group.tsx index 72b54c4c6..c88353919 100644 --- a/components/avatar/Group.tsx +++ b/components/avatar/Group.tsx @@ -6,6 +6,7 @@ import PropTypes from '../_util/vue-types'; import { flattenChildren, getPropsSlot } from '../_util/props-util'; import { tuple } from '../_util/type'; import useConfigInject from '../_util/hooks/useConfigInject'; +import useProviderSize from '../_util/hooks/useSize'; const groupProps = { prefixCls: PropTypes.string, @@ -31,10 +32,8 @@ const Group = defineComponent({ props: groupProps, inheritAttrs: false, setup(props, { slots, attrs }) { - const { prefixCls, direction, size } = useConfigInject('avatar-group', props); - - provide('SizeProvider', size); - + const { prefixCls, direction } = useConfigInject('avatar-group', props); + useProviderSize(props); return () => { const { maxPopoverPlacement = 'top', maxCount, maxStyle } = props; diff --git a/components/config-provider/index.tsx b/components/config-provider/index.tsx index 8a85799df..232012bb5 100644 --- a/components/config-provider/index.tsx +++ b/components/config-provider/index.tsx @@ -89,7 +89,7 @@ export const configProviderProps = { type: Object as PropType<{ ghost: boolean }>, }, componentSize: { - type: Object as PropType, + type: String as PropType, }, direction: { type: String as PropType<'ltr' | 'rtl'>,