diff --git a/packages/vant/src/swipe-cell/README.md b/packages/vant/src/swipe-cell/README.md index bb53e21ea..37e7c9b2f 100644 --- a/packages/vant/src/swipe-cell/README.md +++ b/packages/vant/src/swipe-cell/README.md @@ -91,7 +91,9 @@ export default { return new Promise((resolve) => { showConfirmDialog({ title: 'Are you sure to delete?', - }).then(resolve); + }) + .then(resolve) + .catch(resolve); }); } }; diff --git a/packages/vant/src/swipe-cell/README.zh-CN.md b/packages/vant/src/swipe-cell/README.zh-CN.md index d847da32a..e3dec9713 100644 --- a/packages/vant/src/swipe-cell/README.zh-CN.md +++ b/packages/vant/src/swipe-cell/README.zh-CN.md @@ -98,7 +98,9 @@ export default { return new Promise((resolve) => { showConfirmDialog({ title: '确定删除吗?', - }).then(resolve); + }) + .then(resolve) + .catch(resolve); }); } }; diff --git a/packages/vant/src/swipe-cell/SwipeCell.tsx b/packages/vant/src/swipe-cell/SwipeCell.tsx index b6e127bd5..b1fbccebf 100644 --- a/packages/vant/src/swipe-cell/SwipeCell.tsx +++ b/packages/vant/src/swipe-cell/SwipeCell.tsx @@ -56,6 +56,7 @@ export default defineComponent({ let opened: boolean; let lockClick: boolean; let startOffset: number; + let isInBeforeClosing: boolean; const root = ref(); const leftRef = ref(); @@ -161,9 +162,12 @@ export default defineComponent({ }; const onClick = (position: SwipeCellPosition = 'outside') => { + if (isInBeforeClosing) return; + emit('click', position); if (opened && !lockClick) { + isInBeforeClosing = true; callInterceptor(props.beforeClose, { args: [ { @@ -171,7 +175,12 @@ export default defineComponent({ position, }, ], - done: () => close(position), + done: () => { + isInBeforeClosing = false; + close(position); + }, + canceled: () => (isInBeforeClosing = false), + error: () => (isInBeforeClosing = false), }); } }; diff --git a/packages/vant/src/swipe-cell/demo/index.vue b/packages/vant/src/swipe-cell/demo/index.vue index 9d224bf9d..25a433043 100644 --- a/packages/vant/src/swipe-cell/demo/index.vue +++ b/packages/vant/src/swipe-cell/demo/index.vue @@ -38,13 +38,9 @@ const beforeClose = ({ position }: { position: string }) => { case 'outside': return true; case 'right': - return new Promise((resolve) => { - showConfirmDialog({ - title: t('confirm'), - }).then(() => { - resolve(true); - }); - }); + return showConfirmDialog({ + title: t('confirm'), + }) as Promise; } }; diff --git a/packages/vant/src/swipe-cell/test/index.spec.js b/packages/vant/src/swipe-cell/test/index.spec.js index 4e6c77889..56ac7a42f 100644 --- a/packages/vant/src/swipe-cell/test/index.spec.js +++ b/packages/vant/src/swipe-cell/test/index.spec.js @@ -37,15 +37,29 @@ test('should allow to drag to show right part', async () => { expect(track.style.transform).toEqual('translate3d(-100px, 0, 0)'); }); -test('should call beforeClose before closing', () => { +test('should call beforeClose before closing', async () => { let position; + let clickPosition; + let usePromise; + let promiseRet; const wrapper = mount(SwipeCell, { ...defaultProps, props: { ...defaultProps.props, + onClick(position) { + clickPosition = position; + }, beforeClose(params) { - ({ position } = params); + if (usePromise) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(promiseRet); + }, 100); + }); + } else { + ({ position } = params); + } }, }, }); @@ -66,6 +80,17 @@ test('should call beforeClose before closing', () => { wrapper.vm.close(); expect(track.style.transform).toEqual('translate3d(0px, 0, 0)'); + + usePromise = true; + promiseRet = false; + wrapper.vm.open('right'); + wrapper.find('.van-swipe-cell__right').trigger('click'); + expect(clickPosition).toEqual('right'); + wrapper.trigger('click'); + expect(clickPosition).toEqual('right'); + await later(200); + wrapper.trigger('click'); + expect(clickPosition).toEqual('cell'); }); test('should close swipe cell after clicked', async () => { diff --git a/packages/vant/src/utils/interceptor.ts b/packages/vant/src/utils/interceptor.ts index e9f4d578a..bd2f0c868 100644 --- a/packages/vant/src/utils/interceptor.ts +++ b/packages/vant/src/utils/interceptor.ts @@ -10,10 +10,12 @@ export function callInterceptor( args = [], done, canceled, + error, }: { args?: unknown[]; done: () => void; canceled?: () => void; + error?: () => void; }, ) { if (interceptor) { @@ -29,7 +31,7 @@ export function callInterceptor( canceled(); } }) - .catch(noop); + .catch(error || noop); } else if (returnVal) { done(); } else if (canceled) { diff --git a/packages/vant/src/utils/test/interceptor.spec.ts b/packages/vant/src/utils/test/interceptor.spec.ts index 5459ef75f..80ce9970e 100644 --- a/packages/vant/src/utils/test/interceptor.spec.ts +++ b/packages/vant/src/utils/test/interceptor.spec.ts @@ -3,36 +3,61 @@ import { callInterceptor } from '../interceptor'; test('callInterceptor', async () => { const done = vi.fn(); - callInterceptor(undefined, { done }); + const canceled = vi.fn(); + const error = vi.fn(); + + callInterceptor(undefined, { done, canceled, error }); expect(done).toHaveBeenCalledTimes(1); + expect(canceled).toHaveBeenCalledTimes(0); + expect(error).toHaveBeenCalledTimes(0); callInterceptor(() => false, { done, + canceled, + error, }); expect(done).toHaveBeenCalledTimes(1); + expect(canceled).toHaveBeenCalledTimes(1); + expect(error).toHaveBeenCalledTimes(0); callInterceptor(() => true, { done, + canceled, + error, }); expect(done).toHaveBeenCalledTimes(2); + expect(canceled).toHaveBeenCalledTimes(1); + expect(error).toHaveBeenCalledTimes(0); callInterceptor(() => Promise.resolve(false), { done, + canceled, + error, }); await later(); expect(done).toHaveBeenCalledTimes(2); + expect(canceled).toHaveBeenCalledTimes(2); + expect(error).toHaveBeenCalledTimes(0); callInterceptor(() => Promise.resolve(true), { done, + canceled, + error, }); await later(); expect(done).toHaveBeenCalledTimes(3); + expect(canceled).toHaveBeenCalledTimes(2); + expect(error).toHaveBeenCalledTimes(0); callInterceptor(() => Promise.reject(), { done, + canceled, + error, }); await later(); expect(done).toHaveBeenCalledTimes(3); + expect(canceled).toHaveBeenCalledTimes(2); + expect(error).toHaveBeenCalledTimes(1); callInterceptor( (...args) => { @@ -42,8 +67,12 @@ test('callInterceptor', async () => { { args: ['foo'], done, + canceled, + error, }, ); expect(done).toHaveBeenCalledTimes(3); + expect(canceled).toHaveBeenCalledTimes(3); + expect(error).toHaveBeenCalledTimes(1); });