Vue3 组件完全指南代码

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>

代码实现要点:

  1. 基础按钮组件采用组合式API封装,支持类型校验和插槽内容34
  2. 模态框组件实现Transition动画效果和具名插槽59
  3. 通过useModal Hook实现函数式调用组件18
  4. 全局注册常用基础组件提升复用性26
  5. 采用TypeScript接口规范props类型3
  6. 样式使用scoped隔离避免污染1112
  7. 包含完整的组件通信机制
相关推荐
林强1814 小时前
前端文件预览docx、pptx和xlsx
前端
计算机学姐4 小时前
基于微信小程序的高校班务管理系统【2026最新】
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis
像是套了虚弱散6 小时前
DevEco Studio与Web联合开发:打造鸿蒙混合应用的全景指南
开发语言·前端·华为·harmonyos·鸿蒙
衬衫chenshan7 小时前
【CTF】强网杯2025 Web题目writeup
前端
飞翔的佩奇7 小时前
【完整源码+数据集+部署教程】【天线&水】舰船战舰检测与分类图像分割系统源码&数据集全套:改进yolo11-repvit
前端·python·yolo·计算机视觉·数据集·yolo11·舰船战舰检测与分类图像分割系统
哆啦A梦15888 小时前
点击Top切换数据
前端·javascript·vue.js
程序猿追8 小时前
Vue组件化开发
前端·html
艾德金的溪9 小时前
redis-7.4.6部署安装
前端·数据库·redis·缓存
小光学长9 小时前
基于Vue的2025年哈尔滨亚冬会志愿者管理系统5zqg6m36(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
@PHARAOH9 小时前
WHAT - 受控组件和非受控组件
前端·javascript·react.js