← Back to Lab
// Engineering2026.05.042 min read
Vue3 组件封装哲学:从 RTSP 播放器到通用表单
在多个项目中沉淀的 Vue3 组件封装实践——RTSP 播放器自动重连、ActionOverflow 权限按钮、动态表单配置化生成,以及拖拽上传等通用组件的设计思路。
Vue3 组件封装哲学
核心原则
好的组件封装不是把代码藏起来,而是让团队不需要重复做同样的决策。
RTSP 播放器:自动重连
<template>
<video ref="videoRef" @error="handleError" />
</template>
<script setup lang="ts">
const props = defineProps<{
url: string
autoReconnect?: boolean
maxRetry?: number
}>()
const videoRef = ref<HTMLVideoElement>()
let retryCount = 0
const handleError = () => {
if (!props.autoReconnect) return
if (retryCount >= (props.maxRetry ?? 3)) return
setTimeout(() => {
retryCount++
loadStream()
}, 2000 * retryCount)
}
const loadStream = () => {
if (!videoRef.value) return
videoRef.value.src = props.url
videoRef.value.play()
}
onMounted(loadStream)
</script>
ActionOverflow 权限按钮
根据用户权限动态显示/隐藏按钮:
// 全局注册
app.directive('permission', {
mounted(el, binding) {
const permissions = useUserStore().permissions
if (!permissions.includes(binding.value)) {
el.parentNode?.removeChild(el)
}
}
})
动态表单:配置化生成
interface FormField {
key: string
label: string
type: 'input' | 'select' | 'date' | 'switch'
rules?: Rule[]
options?: { label: string; value: any }[]
dynamic?: boolean // 动态表单项
}
const formConfig: FormField[] = [
{ key: 'name', label: '姓名', type: 'input', rules: [required] },
{ key: 'type', label: '类型', type: 'select', options: [...] },
]
通过配置文件生成表单项,减少模板冗余代码超 50%。
拖拽上传
<template>
<div
class="upload-zone"
@dragover.prevent="dragging = true"
@dragleave.prevent="dragging = false"
@drop.prevent="handleDrop"
>
<slot />
</div>
</template>
沉淀规范
- 统一样式与代码规范(ESLint / Prettier)
- 通用组件全局注册,降低团队冲突率
- 每个组件配套 TypeScript 类型定义