APIs
参数 说明 类型 默认值 必传 title 确认框的标题 string | slot ‘’ false description 确认框的内容描述 string | slot ‘’ false content 展示的文本 string | slot ‘’ false icon 自定义弹出确认框 Icon
图标 string | slot ‘’ false maxWidth 弹出确认框内容最大宽度 string | number ‘auto’ false cancelText 取消按钮文字 string | slot ‘取消’ false cancelType 取消按钮类型 string ‘default’ false okText 确认按钮文字 string | slot ‘确定’ false okType 确认按钮类型 string ‘primary’ false showCancel 是否显示取消按钮 boolean true false
Events
事件名称 说明 参数 cancel 点击取消的回调 (e: Event) => void ok 点击确认的回调 (e: Event) => void openChange 显示隐藏的回调 (visible: boolean) => void
创建弹出确认组件Popconfirm.vue
< script setup lang= "ts" >
import { ref, computed, onMounted } from 'vue'
import type { Slot } from 'vue'
interface Props {
title? : string | Slot
description? : string | Slot
content? : string | Slot
icon? : string | Slot
maxWidth? : string | number
cancelText? : string | Slot
cancelType? : string
okText? : string | Slot
okType? : string
showCancel? : boolean
}
const props = withDefaults ( defineProps < Props> ( ) , {
title: '' ,
description: '' ,
content: '' ,
icon: '' ,
maxWidth: 'auto' ,
cancelText: '取消' ,
cancelType: 'default' ,
okText: '确定' ,
okType: 'primary' ,
showCancel: true
} )
const popMaxWidth = computed ( ( ) => {
if ( typeof props. maxWidth === 'number' ) {
return props. maxWidth + 'px'
}
return props. maxWidth
} )
const visible = ref ( false )
const desc = ref ( )
const showDesc = ref ( 1 )
onMounted ( ( ) => {
showDesc. value = desc. value. offsetHeight
} )
const top = ref ( 0 )
const left = ref ( 0 )
const contentRef = ref ( )
const popRef = ref ( )
function getPosition ( ) {
const contentWidth = contentRef. value. offsetWidth
const popWidth = popRef. value. offsetWidth
const popHeight = popRef. value. offsetHeight
top. value = popHeight + 4
left. value = ( popWidth - contentWidth) / 2
}
const activeBlur = ref ( false )
function onEnter ( ) {
activeBlur. value = false
}
function onLeave ( ) {
activeBlur. value = true
popRef. value. focus ( )
}
function onBlur ( ) {
visible. value = false
emits ( 'openChange' , false )
}
const emits = defineEmits ( [ 'cancel' , 'ok' , 'openChange' ] )
function onOpen ( ) {
visible. value = ! visible. value
if ( visible. value) {
getPosition ( )
}
emits ( 'openChange' , visible. value)
}
function onCancel ( e: Event) {
visible. value = false
emits ( 'openChange' , false )
emits ( 'cancel' , e)
}
function onOk ( e: Event) {
visible. value = false
emits ( 'openChange' , false )
emits ( 'ok' , e)
}
< / script>
< template>
< div class = "m-popconfirm" >
< div
ref= "popRef"
tabindex= "1"
class = "m-pop-content"
: class = "{'show-pop': visible}"
: style= "`max-width: ${popMaxWidth}; top: ${-top}px; left: ${-left}px;`"
@ blur = "activeBlur ? onBlur() : () => false" >
< div class = "m-pop" >
< div class = "m-pop-message" >
< span class = "m-icon" >
< slot name= "icon" >
< svg focusable= "false" class = "u-icon" data- icon= "exclamation-circle" width= "1em" height= "1em" fill= "currentColor" aria- hidden= "true" viewBox= "64 64 896 896" > < path d= "M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z" > < / path> < / svg>
< / slot>
< / span>
< div class = "m-title" : class = "{'font-weight': showDesc}" >
< slot name= "title" > { { title } } < / slot>
< / div>
< / div>
< div class = "m-pop-description" ref= "desc" v- if = "showDesc" >
< slot name= "description" > { { description } } < / slot>
< / div>
< div class = "m-pop-buttons" >
< Button v- if = "showCancel" @ click = "onCancel" size= "small" : type= cancelType> { { cancelText } } < / Button>
< Button @ click = "onOk" size= "small" : type= okType> { { okText } } < / Button>
< / div>
< / div>
< div class = "m-pop-arrow" >
< span class = "u-pop-arrow" > < / span>
< / div>
< / div>
< div
ref= "contentRef"
@ click = "onOpen"
@ mouseenter = "onEnter"
@ mouseleave = "onLeave" >
< slot> { { content } } < / slot>
< / div>
< / div>
< / template>
< style lang= "less" scoped>
. m- popconfirm {
position: relative;
display: inline- block;
. m- pop- content {
position: absolute;
z- index: 999 ;
width: max- content;
padding- bottom: 12px;
outline: none;
pointer- events: none;
opacity: 0 ;
transform- origin: 50 % 75 % ;
transform: scale ( .8 ) ;
- ms- transform: scale ( .8 ) ;
- webkit- transform: scale ( .8 ) ;
transition: transform . 25s, opacity . 25s;
. m- pop {
min- width: 32px;
min- height: 32px;
padding: 12px;
font- size: 14px;
color: rgba ( 0 , 0 , 0 , .88 ) ;
line- height: 1.5714285714285714 ;
text- align: start;
text- decoration: none;
word- wrap: break - word;
cursor: auto;
user- select: text;
background- color: #FFF ;
border- radius: 8px;
box- shadow: 0 6px 16px 0 rgba ( 0 , 0 , 0 , .08 ) , 0 3px 6px - 4px rgba ( 0 , 0 , 0 , .12 ) , 0 9px 28px 8px rgba ( 0 , 0 , 0 , .05 ) ;
. m- pop- message {
position: relative;
margin- bottom: 8px;
font- size: 14px;
display: flex;
flex- wrap: nowrap;
align- items: start;
. m- icon {
content: '\f8f5' ;
flex: none;
line- height: 1 ;
padding- top: 4px;
display: inline- block;
text- align: center;
. u- icon {
display: inline- block;
line- height: 1 ;
fill: #faad14;
}
}
. m- title {
flex: auto;
margin- inline- start: 8px;
}
. font- weight {
font- weight: 600 ;
}
}
. m- pop- description {
position: relative;
margin- inline- start: 22px;
margin- bottom: 8px;
font- size: 14px;
}
. m- pop- buttons {
text- align: end;
& > . m- btn- wrap {
margin- inline- start: 8px;
}
}
}
. m- pop- arrow {
position: absolute;
z- index: 9 ;
left: 50 % ;
bottom: 12px;
transform: translateX ( - 50 % ) translateY ( 100 % ) rotate ( 180deg) ;
display: block;
border- radius: 0 0 2px;
pointer- events: none;
width: 32px;
height: 32px;
overflow: hidden;
& : : before {
position: absolute;
bottom: 0 ;
inset- inline- start: 0 ;
width: 32px;
height: 8px;
background: #FFF ;
clip- path: path ( 'M 6.343145750507619 8 A 4 4 0 0 0 9.17157287525381 6.82842712474619 L 14.585786437626904 1.414213562373095 A 2 2 0 0 1 17.414213562373096 1.414213562373095 L 22.82842712474619 6.82842712474619 A 4 4 0 0 0 25.65685424949238 8 Z' ) ;
content: "" ;
}
& : : after {
position: absolute;
width: 11 . 31370849898476px;
height: 11 . 31370849898476px;
bottom: 0 ;
inset- inline: 0 ;
margin: auto;
border- radius: 0 0 2px 0 ;
transform: translateY ( 50 % ) rotate ( - 135deg) ;
box- shadow: 3px 3px 7px rgba ( 0 , 0 , 0 , .1 ) ;
z- index: 0 ;
background: transparent;
content: "" ;
}
}
}
. show- pop {
pointer- events: auto;
opacity: 1 ;
transform: scale ( 1 ) ;
- ms- transform: scale ( 1 ) ;
- webkit- transform: scale ( 1 ) ;
}
}
< / style>
在要使用的页面引入
其中引入使用了 Vue3按钮(Button)、Vue3全局提示(Message)
< script setup lang= "ts" >
import Popconfirm from './Popconfirm.vue'
import Button from './Button.vue'
import Message from './Message.vue'
import { ref } from 'vue'
const message = ref ( )
const confirm = ( e: MouseEvent) => {
console . log ( e)
message. value. success ( 'Click on Yes' )
}
const cancel = ( e: MouseEvent) => {
console . log ( e)
message. value. error ( 'Click on No' )
}
< / script>
< template>
< div class = "ml120" >
< h1> Popconfirm 弹出确认< / h1>
< h2 class = "mt30 mb10" > 基本使用< / h2>
< Popconfirm
title= "Are you sure delete this task?"
description= "This will have other effects..."
@ ok = "confirm"
@ cancel = "cancel" >
< Button type= "danger" > Delete< / Button>
< / Popconfirm>
< h2 class = "mt30 mb10" > 自定义按钮文字< / h2>
< Popconfirm title= "Are you sure?" ok- text= "Yes" cancel- text= "No" >
< Button type= "danger" > Delete< / Button>
< / Popconfirm>
< h2 class = "mt30 mb10" > 自定义 Icon 图标< / h2>
< Popconfirm title= "Are you sure?" >
< template #icon>
< svg focusable= "false" class = "u-svg" data- icon= "question-circle" width= "1em" height= "1em" fill= "currentColor" aria- hidden= "true" viewBox= "64 64 896 896" > < path d= "M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" > < / path> < path d= "M623.6 316.7C593.6 290.4 554 276 512 276s-81.6 14.5-111.6 40.7C369.2 344 352 380.7 352 420v7.6c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V420c0-44.1 43.1-80 96-80s96 35.9 96 80c0 31.1-22 59.6-56.1 72.7-21.2 8.1-39.2 22.3-52.1 40.9-13.1 19-19.9 41.8-19.9 64.9V620c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-22.7a48.3 48.3 0 0130.9-44.8c59-22.7 97.1-74.7 97.1-132.5.1-39.3-17.1-76-48.3-103.3zM472 732a40 40 0 1080 0 40 40 0 10-80 0z" > < / path> < / svg>
< / template>
< Button type= "danger" > Delete< / Button>
< / Popconfirm>
< h2 class = "mt30 mb10" > 隐藏取消按钮< / h2>
< Popconfirm
title= "friendly reminder ..."
: show- cancel= "false" >
< Button type= "primary" > Hidden Cancel Btn< / Button>
< / Popconfirm>
< Message ref= "message" / >
< / div>
< / template>
< style lang= "less" scoped>
. u- svg {
fill: #ff4d4f;
}
< / style>