diff --git a/packages/vant/src/slider/README.md b/packages/vant/src/slider/README.md index d73c8bed5..3c653d764 100644 --- a/packages/vant/src/slider/README.md +++ b/packages/vant/src/slider/README.md @@ -175,11 +175,11 @@ export default { ### Slots -| Name | Description | SlotProps | -| ------------ | --------------------------------- | ------------------- | -| button | Custom button | _{ value: number }_ | -| left-button | Custom left button in range mode | _{ value: number }_ | -| right-button | Custom right button in range mode | _{ value: number }_ | +| Name | Description | SlotProps | +| --- | --- | --- | +| button | Custom button | _{ value: number, dragging: boolean }_ | +| left-button | Custom left button in range mode | _{ value: number, dragging: boolean, dragIndex?: number }_ | +| right-button | Custom right button in range mode | _{ value: number, dragging: boolean, dragIndex?: number }_ | ### Types diff --git a/packages/vant/src/slider/README.zh-CN.md b/packages/vant/src/slider/README.zh-CN.md index d40e270b1..f52c6697b 100644 --- a/packages/vant/src/slider/README.zh-CN.md +++ b/packages/vant/src/slider/README.zh-CN.md @@ -177,11 +177,11 @@ export default { ### Slots -| 名称 | 说明 | 参数 | -| ------------ | ---------------------------------- | ------------------- | -| button | 自定义滑块按钮 | _{ value: number }_ | -| left-button | 自定义左侧滑块按钮(双滑块模式下) | _{ value: number }_ | -| right-button | 自定义右侧滑块按钮(双滑块模式下) | _{ value: number }_ | +| 名称 | 说明 | 参数 | +| --- | --- | --- | +| button | 自定义滑块按钮 | _{ value: number, dragging: boolean }_ | +| left-button | 自定义左侧滑块按钮(双滑块模式下) | _{ value: number, dragging: boolean, dragIndex?: number }_ | +| right-button | 自定义右侧滑块按钮(双滑块模式下) | _{ value: number, dragging: boolean, dragIndex?: number }_ | ### 类型定义 diff --git a/packages/vant/src/slider/Slider.tsx b/packages/vant/src/slider/Slider.tsx index e069190c2..07a8e715d 100644 --- a/packages/vant/src/slider/Slider.tsx +++ b/packages/vant/src/slider/Slider.tsx @@ -273,15 +273,23 @@ export default defineComponent({ }; const renderButtonContent = (value: number, index?: 0 | 1) => { + const dragging = dragStatus.value === 'dragging'; + if (typeof index === 'number') { const slot = slots[index === 0 ? 'left-button' : 'right-button']; + let dragIndex; + + if (dragging && Array.isArray(current)) { + dragIndex = current[0] > current[1] ? buttonIndex ^ 1 : buttonIndex; + } + if (slot) { - return slot({ value }); + return slot({ value, dragging, dragIndex }); } } if (slots.button) { - return slots.button({ value }); + return slots.button({ value, dragging }); } return ( diff --git a/packages/vant/src/slider/test/index.spec.ts b/packages/vant/src/slider/test/index.spec.ts index 966588e55..3e27b876f 100644 --- a/packages/vant/src/slider/test/index.spec.ts +++ b/packages/vant/src/slider/test/index.spec.ts @@ -16,6 +16,16 @@ function mockRect(vertical?: boolean) { }); } +function testSlotReceivedParams( + slot: ReturnType, + dragging: boolean, + dragIndex?: number +) { + const latestParams = slot.mock.calls.at(-1)![0]; + expect(latestParams.dragging).toEqual(dragging); + expect(latestParams.dragIndex).toEqual(dragIndex); +} + test('should emit "update:modelValue" event after dragging button', () => { const wrapper = mount(Slider, { props: { @@ -225,20 +235,84 @@ test('should format v-model with step correctly', async () => { expect(wrapper.emitted('update:modelValue')![0]).toEqual([31]); }); +test('should render button slot correctly', async () => { + const buttonSlot = jest.fn(); + const wrapper = mount(Slider, { + props: { + modelValue: 30, + }, + slots: { + button: buttonSlot, + }, + }); + + expect(buttonSlot.mock.calls[0]).toEqual([{ value: 30, dragging: false }]); + + const button = wrapper.find('.van-slider__button-wrapper'); + + trigger(button, 'touchstart', 50, 0); + trigger(button, 'touchmove', 50, 0); + await later(); + testSlotReceivedParams(buttonSlot, true); + + trigger(button, 'touchend', 50, 0); + await later(); + testSlotReceivedParams(buttonSlot, false); +}); + test('should render left-button、right-button slot correctly', async () => { + const leftButtonSlot = jest.fn(); + const rightButtonSlot = jest.fn(); const wrapper = mount(Slider, { props: { range: true, modelValue: [30, 80], }, slots: { - 'left-button': ({ value }) => `left-${value}`, - 'right-button': ({ value }) => `right-${value}`, + 'left-button': (params) => { + leftButtonSlot(params); + return `left-${params.value}`; + }, + 'right-button': (params) => { + rightButtonSlot(params); + return `right-${params.value}`; + }, }, }); - await later(); + expect(leftButtonSlot.mock.calls[0]).toEqual([ + { value: 30, dragging: false, dragIndex: undefined }, + ]); + expect(rightButtonSlot.mock.calls[0]).toEqual([ + { value: 80, dragging: false, dragIndex: undefined }, + ]); expect(wrapper.html()).toMatchSnapshot(); + + const [leftButton, rightButton] = wrapper.findAll( + '.van-slider__button-wrapper' + ); + + trigger(leftButton, 'touchstart', 50, 0); + trigger(leftButton, 'touchmove', 50, 0); + await later(); + testSlotReceivedParams(leftButtonSlot, true, 0); + testSlotReceivedParams(rightButtonSlot, true, 0); + + trigger(leftButton, 'touchend', 50, 0); + await later(); + testSlotReceivedParams(leftButtonSlot, false, undefined); + testSlotReceivedParams(rightButtonSlot, false, undefined); + + trigger(rightButton, 'touchstart', 50, 0); + trigger(rightButton, 'touchmove', 50, 0); + await later(); + testSlotReceivedParams(leftButtonSlot, true, 1); + testSlotReceivedParams(rightButtonSlot, true, 1); + + trigger(rightButton, 'touchend', 50, 0); + await later(); + testSlotReceivedParams(leftButtonSlot, false, undefined); + testSlotReceivedParams(rightButtonSlot, false, undefined); }); test('should render reversed slider correctly', () => {