Skip to content

确认弹出框 Popconfirm

一个有确认按钮的弹出框。

Popconfirm 与 Popover 在交互上类似,但更侧重于提供确认(确认/取消)类的轻量化操作。

基础使用

通过 content 属性设置显示的提示文本,默认会展示图标、文本与底部按钮(确认/取消)。

<template>
	<px-space>
		<px-popconfirm content="Are you sure you want to delete this item?">
			<px-button theme="danger">Delete</px-button>
		</px-popconfirm>
		<px-popconfirm>
			<template #content>
				<div>
					Shouldn't we make the warning mark bigger?<br />
					It's hard to notice as is.
				</div>
			</template>
			<px-button>Confirm</px-button>
		</px-popconfirm>
	</px-space>
</template>

弹出位置

Popconfirm 弹出框提供 9 种展示位置。

placement 属性决定弹出的位置。该属性值格式为:[方向]-[对齐位置],分别是'top''right''bottom''left''top-start''top-end''right-start''right-end''bottom-start''bottom-end''left-start''left-end',有四个展示方向,和三种对齐方式,默认的 placementtop

<template>
	<div class="box">
		<div class="left">
			<px-popconfirm
				v-for="item in ['left-start', 'left', 'left-end']"
				:key="item"
				:placement="item"
				:content="getContent(item)"
			>
				<px-button>{{ getLabel(item) }}</px-button>
			</px-popconfirm>
		</div>
		<div class="center">
			<div class="top">
				<px-popconfirm
					v-for="item in ['top-start', 'top', 'top-end']"
					:key="item"
					:placement="item"
					:content="getContent(item)"
				>
					<px-button>{{ getLabel(item) }}</px-button>
				</px-popconfirm>
			</div>
			<div class="bottom">
				<px-popconfirm
					v-for="item in ['bottom-start', 'bottom', 'bottom-end']"
					:key="item"
					:placement="item"
					:content="getContent(item)"
				>
					<px-button>{{ getLabel(item) }}</px-button>
				</px-popconfirm>
			</div>
		</div>
		<div class="right">
			<px-popconfirm
				v-for="item in ['right-start', 'right', 'right-end']"
				:key="item"
				:placement="item"
				:content="getContent(item)"
			>
				<px-button>{{ getLabel(item) }}</px-button>
			</px-popconfirm>
		</div>
	</div>
</template>

<script setup lang="ts">
const getLabel = (placement: string) => {
	return placement.replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase())
}

const getContent = (placement: string) => {
	let contentArr: string[] = []
	if (placement.includes('-')) {
		const [pos, sub] = placement.split('-')
		contentArr = [capitalize(pos), capitalize(sub), 'Popover']
	} else {
		contentArr = [capitalize(placement), 'Popover']
	}

	return placement.startsWith('top') || placement.startsWith('bottom')
		? contentArr.join(' ')
		: contentArr.join('\n')
}

const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1)
</script>

<style lang="css" scoped>
.box {
	display: flex;
	width: 600px;
	height: 350px;
	margin-left: 100px;
	margin-top: 64px;
	margin-bottom: 64px;
}
.left,
.right {
	flex-shrink: 0;
	display: flex;
	flex-direction: column;
	justify-content: space-around;
}
.left {
	align-items: flex-start;
}
.right {
	align-items: flex-end;
}
.center {
	flex: 1;
	display: flex;
	flex-direction: column;
}
.top,
.bottom {
	display: flex;
	justify-content: space-around;
}
.top {
	flex: 1;
}
</style>

受控模式

传入 visible 属性进入受控模式;不传或传 undefined 则为非受控模式,可使用 defaultVisible 指定初始显示。组件会触发 update:visible 事件以配合 v-model

<template>
	<px-popconfirm content="Controlled confirm" v-model:visible="visible">
		<px-button>Controlled {{ visible }}</px-button>
	</px-popconfirm>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(false)
</script>

异步确认

传入 onBeforeOk 后,在确认时将会等待 onBeforeOk 执行完成,若结果不为 false 再执行后续代码。

<template>
	<px-popconfirm content="This will run an async check" :onBeforeOk="beforeOk">
		<px-button>Async Confirm</px-button>
	</px-popconfirm>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const calls = ref(0)
const beforeOk = async () => {
	calls.value += 1
	if (calls.value % 2 === 1) {
		await new Promise((r) => setTimeout(r, 500))
		return false
	}
	await new Promise((r) => setTimeout(r, 500))
	return true
}
</script>

自定义底部与图标

通过 footer 插槽可以自定义整个底部区域。若需要自定义图标,可使用 icon 插槽,showIcon 控制是否展示图标;若只需要更改按钮文字 / 属性,使用 okTextcancelText 以及 okButtonPropscancelButtonProps

<template>
	<px-space>
		<px-popconfirm content="Custom Icon example">
			<template #icon>
				<IconMinds />
			</template>
			<px-button>Custom Icon</px-button>
		</px-popconfirm>
		<px-popconfirm content="No Icon example" :show-icon="false">
			<px-button>No Icon</px-button>
		</px-popconfirm>
		<px-popconfirm
			content="Custom Button example"
			ok-text="Yes, delete"
			cancel-text="No, keep it"
			cancel-button-props="{ theme: 'info' }"
			ok-button-props="{ theme: 'danger' }"
		>
			<px-button>Custom Button</px-button>
		</px-popconfirm>
		<px-popconfirm content="Custom footer example" v-model:visible="visible4CustomFooter">
			<template #footer> Custom Footer Content </template>
			<px-button>Custom Footer</px-button>
		</px-popconfirm>
	</px-space>
</template>

<script setup lang="tsx">
import { ref } from 'vue'
import { IconMinds } from '@pixelium/web-vue/icon-hn/es'

const visible4CustomFooter = ref(false)
</script>

禁用状态

传入 disabled 设置禁用状态,此时触发方式将失效,弹出层不会被打开。

<template>
	<px-popconfirm content="This popconfirm is disabled" disabled>
		<px-button>Disabled</px-button>
	</px-popconfirm>
</template>

API

PopconfirmProps

属性类型可选默认值描述版本
contentstring确认弹出框文本内容。0.1.0
visibleboolean | null是否显示(受控模式,支持 v-model)。0.1.0
defaultVisibleboolean | null非受控模式下默认的显示状态。0.1.0
loadingbooleanfalse传入 loading 则用于控制确认按钮 loading 状态。0.1.0
placement'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end''top'弹出位置。0.1.0
okTextstring确认按钮文本。0.1.0
cancelTextstring取消按钮文本。0.1.0
showIconbooleantrue是否显示默认图标。0.1.0
showCancelbooleantrue是否显示取消按钮。0.1.0
showFooterbooleantrue是否显示底部区域。0.1.0
offsetnumber8弹出偏移距离(px)。0.1.0
variant'dark' | 'light''light'组件样式变体。0.1.0
arrowbooleantrue是否展示箭头。0.1.0
disabledbooleanfalse是否禁用。0.1.0
zIndexnumber弹出层 z-index0.1.0
rootHTMLElement | string'body'挂载元素。0.1.0
destroyOnHidebooleanfalse隐藏时是否销毁内容。0.1.0
popoverPropsOmit<PopoverProps, 'visible' | 'content' | 'defaultVisible'> & EmitEvent<PopoverEvents>透传给内部 Popover 的属性。0.1.0
okButtonPropsButtonProps & EmitEvent<ButtonEvents> & RestAttrs传给确认按钮的属性以及事件。0.1.0
cancelButtonPropsButtonProps & EmitEvent<ButtonEvents> & RestAttrs传给取消按钮的属性以及事件。0.1.0
containerPropsRestAttrs透传 DOM 属性到容器区域。0.1.0
contentPropsRestAttrs透传 DOM 属性到内容区域容器。0.1.0
footerPropsRestAttrs透传 DOM 属性到底部区域容器。0.1.0

PopconfirmEvents

事件参数描述版本
update:visiblevalue: booleanv-model 更新时触发。0.1.0
beforeOk用于异步确认,需返回一个 Promise<boolean | void> | boolean | void 类型的数据判断是否成功,await 操作后不为 false 即为确认成功。0.1.0
okevent: MouseEvent点击确认按钮时触发(在 onBeforeOk 通过时)。0.1.0
cancelevent: MouseEvent | KeyboardEvent点击取消按钮时触发。0.1.0
closee: MouseEvent弹出层关闭时触发。0.1.0
opene: MouseEvent弹出层打开时触发。0.1.0

PopconfirmSlots

插槽参数描述版本
default触发元素插槽。0.1.0
content自定义内容。0.1.0
icon自定义图标。0.1.0
footer自定义底部。0.1.0

PopconfirmExpose

属性类型可选默认值描述版本
open() => void打开确认弹出框。0.1.0
close() => void关闭确认弹出框。0.1.0

RestAttrs

ts
import type { StyleValue } from 'vue'

export type VueClassValue = string | Record<string, any> | VueClassValue[]
export type VueStyleValue = StyleValue

export type RestAttrs = {
	style?: VueStyleValue | null
	class?: VueClassValue | null
	[x: string]: any
}

EmitEvent

ts
export type EmitEvent<T extends Record<string, any>> = {
	[K in keyof T as `on${Capitalize<K & string>}`]?: (...args: T[K]) => void
}