diff --git a/packages/vant-cli/site/desktop/components/Content.vue b/packages/vant-cli/site/desktop/components/Content.vue index e1eb949af..7c53568fd 100644 --- a/packages/vant-cli/site/desktop/components/Content.vue +++ b/packages/vant-cli/site/desktop/components/Content.vue @@ -141,7 +141,7 @@ export default { font-size: 14px; font-family: @van-doc-code-font-family; font-style: normal; - max-width: 400px; + max-width: 300px; -webkit-font-smoothing: auto; } } diff --git a/src/popup/Popup.tsx b/src/popup/Popup.tsx index 343d4e5c3..f68196d64 100644 --- a/src/popup/Popup.tsx +++ b/src/popup/Popup.tsx @@ -16,6 +16,7 @@ import { // Utils import { popupSharedProps } from './shared'; import { createNamespace, extend, isDef } from '../utils'; +import { callInterceptor, Interceptor } from '../utils/interceptor'; // Composables import { useEventListener } from '@vant/use'; @@ -50,6 +51,7 @@ export default defineComponent({ closeable: Boolean, transition: String, iconPrefix: String, + beforeClose: Function as PropType, closeOnPopstate: Boolean, safeAreaInsetBottom: Boolean, position: { @@ -115,11 +117,18 @@ export default defineComponent({ } }; + const triggerClose = () => { + opened = false; + emit('close'); + emit('update:show', false); + }; + const close = () => { if (opened) { - opened = false; - emit('close'); - emit('update:show', false); + callInterceptor({ + interceptor: props.beforeClose, + done: triggerClose, + }); } }; diff --git a/src/popup/README.md b/src/popup/README.md index d9a6e83ef..d144fe3ad 100644 --- a/src/popup/README.md +++ b/src/popup/README.md @@ -136,6 +136,7 @@ export default { | closeable | Whether to show close icon | _boolean_ | `false` | | close-icon | Close icon name | _string_ | `cross` | | close-icon-position | Close Icon Position,can be set to `top-left` `bottom-left` `bottom-right` | _string_ | `top-right` | +| before-close `v3.1.4` | Callback function before close | _(action: string) => boolean \| Promise\_ | - | | icon-prefix `v3.0.18` | Icon className prefix | _string_ | `van-icon` | | transition | Transition, equivalent to `name` prop of [transition](https://v3.vuejs.org/api/built-in-components.html#transition) | _string_ | - | | transition-appear | Whether to apply transition on initial render | _boolean_ | `false` | diff --git a/src/popup/README.zh-CN.md b/src/popup/README.zh-CN.md index 7067789c8..1d09c1564 100644 --- a/src/popup/README.zh-CN.md +++ b/src/popup/README.zh-CN.md @@ -140,6 +140,7 @@ export default { | closeable | 是否显示关闭图标 | _boolean_ | `false` | | close-icon | 关闭[图标名称](#/zh-CN/icon)或图片链接 | _string_ | `cross` | | close-icon-position | 关闭图标位置,可选值为 `top-left`
`bottom-left` `bottom-right` | _string_ | `top-right` | +| before-close `v3.1.4` | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(action: string) => boolean \| Promise\_ | - | | icon-prefix `v3.0.18` | 图标类名前缀,同 Icon 组件的 [class-prefix 属性](#/zh-CN/icon#props) | _string_ | `van-icon` | | transition | 动画类名,等价于 [transition](https://v3.cn.vuejs.org/api/built-in-components.html#transition) 的 `name` 属性 | _string_ | - | | transition-appear | 是否在初始渲染时启用过渡动画 | _boolean_ | `false` | diff --git a/src/popup/test/index.spec.js b/src/popup/test/index.spec.js index b914ab1f3..287c9dfe0 100644 --- a/src/popup/test/index.spec.js +++ b/src/popup/test/index.spec.js @@ -214,3 +214,19 @@ test('should render overlay-content slot correctly', () => { expect(wrapper.html()).toMatchSnapshot(); }); + +test('should allow to prevent close with before-close prop', async () => { + const wrapper = mount(Popup, { + props: { + show: true, + beforeClose: () => false, + }, + }); + + await wrapper.find('.van-overlay').trigger('click'); + expect(wrapper.emitted('update:show')).toBeFalsy(); + + await wrapper.setProps({ beforeClose: () => true }); + await wrapper.find('.van-overlay').trigger('click'); + expect(wrapper.emitted('update:show')[0]).toEqual([false]); +});