Skip to content

Commit

Permalink
fix(Carousel): 修复部分属性响应性失效问题 (#713)
Browse files Browse the repository at this point in the history
Co-authored-by: erictang <[email protected]>
  • Loading branch information
vimplus and erictang authored Mar 29, 2024
1 parent dcefa72 commit b06058a
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 102 deletions.
31 changes: 15 additions & 16 deletions components/carousel/arrow.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import {
defineComponent,
computed,
inject,
Fragment,
Transition,
type ComponentObjectPropsOptions,
} from 'vue';
import { defineComponent, computed, inject, Fragment, Transition } from 'vue';
import { throttle } from 'lodash-es';
import { LeftOutlined, RightOutlined } from '../icon';
import { provideKey } from './const';
import type { CarouselItemData } from './interface';
import type { PropType, ComponentObjectPropsOptions } from 'vue';
import type { CarouselItemData, ArrowType } from './interface';

export default defineComponent({
name: 'FCarouselArrow',
Expand All @@ -22,32 +16,37 @@ export default defineComponent({
type: Boolean,
required: true,
},
showArrow: {
type: String as PropType<ArrowType>,
default: 'hover',
},
activeIndex: Number,
} satisfies ComponentObjectPropsOptions,
setup(props) {
const {
prefixCls,
direction,
rootProps,
slideChildren,
showArrow,
loop,
setActiveItem,
} = inject(provideKey);

const arrowVisible = computed(
() => showArrow !== 'never' && direction.value === 'horizontal',
() =>
props.showArrow !== 'never' && direction.value === 'horizontal',
);

const arrowLeftShow = computed(
() =>
(showArrow === 'always' || props.hover) &&
(loop || props.activeIndex > 0),
(props.showArrow === 'always' || props.hover) &&
(rootProps.loop || props.activeIndex > 0),
);

const arrowRightShow = computed(
() =>
(showArrow === 'always' || props.hover) &&
(loop || props.activeIndex < slideChildren.value.length - 1),
(props.showArrow === 'always' || props.hover) &&
(rootProps.loop ||
props.activeIndex < slideChildren.value.length - 1),
);

const slideItemInStage = (
Expand Down
18 changes: 8 additions & 10 deletions components/carousel/carousel-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ export default defineComponent({
prefixCls,
direction,
wrapperRef,
type: parentType,
loop,
rootProps,
slideChildren,
setActiveItem,
addItem,
Expand Down Expand Up @@ -130,16 +129,15 @@ export default defineComponent({
oldIndex: number,
) => {
const length = slideChildren.value.length;
// eslint-disable-next-line no-undefined
if (parentType !== 'card' && oldIndex !== undefined) {
if (rootProps.type !== 'card' && oldIndex !== undefined) {
itemStatus.animating =
index === activeIndex || index === oldIndex;
}
if (index !== activeIndex && length > 2 && loop) {
if (index !== activeIndex && length > 2 && rootProps.loop) {
index = processIndex(index, activeIndex, length);
}

if (parentType === 'card') {
if (rootProps.type === 'card') {
if (direction.value === 'vertical') {
console.warn(
`[${CAROUSEL_ITEM_NAME}]: ${CAROUSEL_NAME} vertical direction is not supported in card mode.`,
Expand All @@ -164,7 +162,7 @@ export default defineComponent({
};

const onClickSlide = () => {
if (parentType === 'card') {
if (rootProps.type === 'card') {
const index = slideChildren.value
.map((item: CarouselItemData) => item.uid)
.indexOf(instance.uid);
Expand All @@ -175,7 +173,7 @@ export default defineComponent({
onMounted(() => {
addItem({
uid: instance.uid,
key: props.key,
itemkey: props.itemkey,
states: itemStatus,
translateItem,
} as CarouselItemData);
Expand All @@ -191,7 +189,7 @@ export default defineComponent({
v-show={itemReady.value}
class={{
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-card`]: parentType === 'card',
[`${prefixCls}-item-card`]: rootProps.type === 'card',
'is-in-stage': itemStatus.inStage,
'is-hover': itemStatus.hover,
'is-active': itemStatus.active,
Expand All @@ -200,7 +198,7 @@ export default defineComponent({
style={itemStyle.value}
onClick={onClickSlide}
>
{parentType === 'card' && (
{rootProps.type === 'card' && (
<div
v-show={!itemStatus.active}
class={`${prefixCls}-item-mask`}
Expand Down
23 changes: 8 additions & 15 deletions components/carousel/carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
defineComponent,
watch,
ref,
type PropType,
type ComponentObjectPropsOptions,
} from 'vue';
import { defineComponent, watch, ref } from 'vue';
import { useTheme } from '../_theme/useTheme';
import useResize from '../_util/use/useResize';
import { CHANGE_EVENT } from '../_util/constants';
Expand All @@ -14,7 +8,8 @@ import Indicator from './indicator';
import useCarousel from './useCarousel';
import useCarouselStyle from './useCarouselStyle';
import useCarouselPlay from './useCarouselPlay';
import type { Placement } from './interface';
import type { PropType, ComponentObjectPropsOptions } from 'vue';
import type { Placement, ArrowType } from './interface';
import type { ExtractPublicPropTypes } from '../_util/interface';

export const carouselProps = {
Expand Down Expand Up @@ -51,7 +46,7 @@ export const carouselProps = {
default: '',
},
showArrow: {
type: String,
type: String as PropType<ArrowType>,
default: 'hover',
},
type: {
Expand Down Expand Up @@ -79,6 +74,7 @@ export default defineComponent({
emits: [CHANGE_EVENT],
setup(props, { slots, emit, expose }) {
useTheme();

const {
prefixCls,
wrapperRef,
Expand All @@ -92,17 +88,13 @@ export default defineComponent({
} = useCarousel(props);

const { wrapperClass, carouselStyle } = useCarouselStyle({
props,
prefixCls,
height: props.height,
type: props.type,
direction,
});

const { startTimer, pauseTimer } = useCarouselPlay({
interval: props.interval,
initialIndex: props.initialIndex,
autoplay: props.autoplay,
loop: props.loop,
props,
activeIndex,
slideChildren,
});
Expand Down Expand Up @@ -164,6 +156,7 @@ export default defineComponent({
<div class={`${prefixCls}-slides`}>
<Arrow
hover={carouselHover.value}
showArrow={props.showArrow}
activeIndex={activeIndex.value}
/>
<div
Expand Down
8 changes: 4 additions & 4 deletions components/carousel/indicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ export default defineComponent({
}, 300);

return () => (
<ul class={indicatorsClass.value}>
<div class={indicatorsClass.value}>
{slideChildren.value.map(
(item: CarouselItemData, index: number) => (
<li
<div
key={index}
class={[
`${prefixCls}-indicator`,
Expand All @@ -73,10 +73,10 @@ export default defineComponent({
type="button"
class={`${prefixCls}-indicator-btn`}
></button>
</li>
</div>
),
)}
</ul>
</div>
);
},
});
3 changes: 2 additions & 1 deletion components/carousel/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import type { ExtractPublicPropTypes } from '../_util/interface';

export type Placement = 'top' | 'bottom' | 'left' | 'right';
export type Direction = 'horizontal' | 'vertical' | '';
export type ArrowType = 'hover' | 'always' | 'never';

export interface CarouselInst extends ReturnType<typeof useCarousel> {
carouselId?: string;
}

export const carouselItemProps = {
key: {
itemkey: {
type: String,
default: '',
},
Expand Down
6 changes: 2 additions & 4 deletions components/carousel/useCarousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,15 @@ export default function useCarousel(props: CarouselProps) {
});

const itemState = useCarouselItem({
loop: props.loop,
props,
activeIndex,
});

const state = {
prefixCls,
wrapperRef,
direction,
type: props.type,
loop: props.loop,
showArrow: props.showArrow,
rootProps: props,
activeIndex,
...itemState,
};
Expand Down
15 changes: 9 additions & 6 deletions components/carousel/useCarouselItem.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { ref, type Ref } from 'vue';
import { CAROUSEL_NAME } from './const';
import type { CarouselItemData } from './interface';
import type { CarouselProps } from './carousel';

interface UseCarouselItemType {
loop: boolean;
props: CarouselProps;
activeIndex: Ref<number>;
}

export default function useCarouselItem({
loop,
props,
activeIndex,
}: UseCarouselItemType) {
// 子项集合
const slideChildren: Ref<CarouselItemData[]> = ref([]);

const resetItemPosition = (oldIndex?: number | unknown): void => {
slideChildren.value.forEach((item, index) => {
slideChildren.value.forEach((item: CarouselItemData, index: number) => {
item.translateItem(index, activeIndex.value, oldIndex);
});
};
Expand All @@ -31,9 +32,9 @@ export default function useCarouselItem({
const childrenCount = slideChildren.value.length;
const oldIndex = activeIndex.value;
if (index < 0) {
activeIndex.value = loop ? childrenCount - 1 : 0;
activeIndex.value = props.loop ? childrenCount - 1 : 0;
} else if (index >= childrenCount) {
activeIndex.value = loop ? 0 : childrenCount - 1;
activeIndex.value = props.loop ? 0 : childrenCount - 1;
} else {
activeIndex.value = index;
}
Expand All @@ -55,7 +56,9 @@ export default function useCarouselItem({
}

function removeItem(uid: number) {
const index = slideChildren.value.findIndex((item) => item.uid === uid);
const index = slideChildren.value.findIndex(
(item: CarouselItemData) => item.uid === uid,
);
if (index !== -1) {
slideChildren.value.splice(index, 1);
if (activeIndex.value === index) next();
Expand Down
Loading

0 comments on commit b06058a

Please sign in to comment.