or: (val) => ['primary', 'success', 'warning', 'danger'].includes(val)
},
label: String,
disabled: Boolean
})
const emit = defineEmits(['click'])
const handleClick = (e) => {
if (!props.disabled) {
emit('click', e)
}
}
</script>
<style scoped>
.btn {
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}
.primary {
background-color: #409eff;
color: white;
}
.success {
background-color: #67c23a;
color: white;
}
/* 其他样式省略 */
</style>
<template>
<Transition name="fade">
<div v-if="visible" class="modal-mask">
<div class="modal-container">
<div class="modal-header">
<h3>{{ title }}</h3>
<button @click="close">×</button>
</div>
<div class="modal-body">
<slot></slot>
</div>
<div class="modal-footer">
<BaseButton @click="close">取消</BaseButton>
<BaseButton type="primary" @click="confirm">确认</BaseButton>
</div>
</div>
</div>
</Transition>
</template>
<script setup>
import { ref } from 'vue'
import BaseButton from '../BaseButton.vue'
const props = defineProps({
title: String,
visible: Boolean
})
const emit = defineEmits(['close', 'confirm'])
const close = () => emit('close')
const confirm = () => emit('confirm')
</script>
<style scoped>
.modal-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
/* 其他样式省略 */
</style>
import { createApp, h, ref } from 'vue'
import Modal from '../components/Modal/Modal.vue'
export function useModal() {
const visible = ref(false)
const show = (options) => {
visible.value = true
const container = document.createElement('div')
document.body.appendChild(container)
const app = createApp({
render() {
return h(Modal, {
title: options.title,
visible: visible.value,
onClose: () => {
hide()
options?.onClose?.()
},
onConfirm: () => {
hide()
options?.onConfirm?.()
}
}, options.content)
}
})
const hide = () => {
visible.value = false
app.unmount()
document.body.removeChild(container)
}
app.mount(container)
return hide
}
return { show }
}
import { createApp } from 'vue'
import App from './App.vue'
import BaseButton from './components/BaseButton.vue'
const app = createApp(App)
// 全局注册基础组件
app.component('BaseButton', BaseButton)
app.mount('#app')
<template>
<div class="app">
<BaseButton
type="primary"
@click="showModal"
>
打开模态框
</BaseButton>
</div>
</template>
<script setup>
import { useModal } from './hooks/useModal'
const { show } = useModal()
const showModal = () => {
show({
title: '提示',
content: '这是一个通过函数调用的模态框组件',
onConfirm: () => console.log('确认操作'),
onClose: () => console.log('关闭操作')
})
}
</script>
代码实现要点:
- 基础按钮组件采用组合式API封装,支持类型校验和插槽内容34
- 模态框组件实现Transition动画效果和具名插槽59
- 通过useModal Hook实现函数式调用组件18
- 全局注册常用基础组件提升复用性26
- 采用TypeScript接口规范props类型3
- 样式使用scoped隔离避免污染1112
- 包含完整的组件通信机制