
📖 资源简介
最近有朋友问Vue.js 3高级编程:UI组件库开发的学习资料,正好手头有一套比较完整的,就整理出来分享给大家。
✨ 资源亮点
- 内容扎实:48节视频课程,跟着老师一步步操作,从 monorepo 工作区一路做到 Button、ButtonGroup 组件与 Sass 主题体系,比自学摸索快得多。
📚 课程内容
课程大纲
- monorepo 工作区与演示项目搭建
- CSS 命名规范(BEM)与 Sass 变量体系
- Button 组件全属性实现(type / round / disabled / text / link / block / size / icon / loading 等)
- ButtonGroup 组件与属性优先级
- Sass 主题色、层次色生成与 CSS 变量主题定制
资源清单
| 类型 | 数量 |
|---|---|
| 视频教程 | 48 节 |
| 压缩文件 | 0 个 |
| 合计 | 48 |
🛠 核心技术精讲
为什么要自己写一套组件库
用过 Element Plus、Ant Design Vue 的人都知道,业务项目里真正头疼的往往不是”调组件”,而是:主题色要随品牌切换、设计规范要统一、多个业务线要复用同一套基础组件。从零实现一个组件库,本质上是把”Vue3 组合式 API、响应式原理、组件通信、样式工程化、库构建发布”这一整套前端工程能力串起来。本套课程正是以 Button 这个最小但五脏俱全的组件为载体,把组件库开发的关键环节走通。
适合人群:已经能用 Vue3 写业务页面、想进阶到”造轮子”的前端工程师;准备面试组件库 / 中后台方向的同学。
Composition API:组件库组件的标准写法
Vue3 推荐用 <script setup> 语法糖编写组件,组件库也不例外。它比 Options API 更利于逻辑复用与类型推导:
<!-- src/button/Button.vue -->
<script setup>
import { computed } from 'vue'
const props = defineProps({
type: { type: String, default: 'default' }, // primary / success / danger...
size: { type: String, default: 'default' }, // large / small
disabled: Boolean,
loading: Boolean,
round: Boolean,
})
const emit = defineEmits(['click'])
// 用 computed 把 props 映射成 BEM 类名,这正是课程里 is- 方法的思路
const classes = computed(() => ({
[`v-button--${props.type}`]: true,
'is-disabled': props.disabled,
'is-loading': props.loading,
'is-round': props.round,
}))
function handleClick(e) {
if (props.disabled || props.loading) return // loading / 禁用时不响应
emit('click', e)
}
</script>
<template>
<button :class="classes" :disabled="disabled" @click="handleClick">
<span v-if="loading" class="v-button__loading" />
<slot />
</button>
</template>
ref 用于基本类型响应式状态,reactive 用于对象;computed 做派生状态,watch / watchEffect 做副作用监听;生命周期钩子从 onMounted 开始在组合式 API 中按需导入。
响应式原理:Proxy 取代 defineProperty
Vue3 放弃了 Vue2 的 Object.defineProperty,改用 Proxy 代理整个对象,从而能拦截索引、属性新增删除等 defineProperty 无法覆盖的操作。核心是两个动作——依赖收集 track 和 触发更新 trigger:
// 简化版响应式核心(理解思想即可)
let activeEffect = null
function reactive(target) {
return new Proxy(target, {
get(obj, key) {
track(obj, key) // 读:收集当前正在运行的副作用
return obj[key]
},
set(obj, key, value) {
obj[key] = value
trigger(obj, key) // 写:通知所有依赖该 key 的副作用重新执行
return true
},
})
}
每个副作用(如组件渲染函数)在执行前会被标记为 activeEffect,读取响应式属性时把它记进 targetMap -> depsMap -> effects 三层结构;属性一变,就把对应的 effect 重新跑一遍。理解了 track / trigger,再看 watch 为什么能监听、为什么 reactive 解构会丢失响应式,就都通了。
组件通信与插槽
组件库内部大量使用父子通信:父组件通过 props 下发配置,子组件通过 emit 上抛事件,跨层级用 provide / inject(比如 ButtonGroup 向组内 Button 注入间距与对齐方式):
// ButtonGroup.vue 注入上下文
provide('buttonGroup', { gap: '8px', align: 'center' })
// Button.vue 中消费
const group = inject('buttonGroup', null)
插槽是组件库的灵魂。Button 的文字、图标都应通过插槽暴露:默认插槽放主内容,具名插槽放 icon,作用域插槽把数据回传给父级。课程里”第30节 button 组件 slot 插槽”讲的就是这一点。
样式工程化:BEM 命名 + CSS 变量主题
课程用了大量篇幅讲 Sass 与 BEM 命名:block(v-button)、element(v-button__icon)、modifier(v-button--primary),并用 is- 前缀表达状态(is-disabled / is-loading)。主题定制则走 CSS 变量路线,把颜色抽成 :root 变量,换肤只改变量不改组件:
// 主题色变量(课程第40~48节的思路)
:root {
--v-color-primary: #409eff;
--v-color-success: #67c23a;
}
.v-button--primary {
background-color: var(--v-color-primary);
&:hover { filter: brightness(1.1); }
}
层次色(同色系的 hover / active / disabled 色阶)则由 Sass 函数基于主题色批量计算生成,避免手维护十几组颜色。
全局注册、按需加载与 Tree Shaking
组件库要同时支持全量引入与按需引入:
// src/index.js
import Button from './button'
import ButtonGroup from './button-group'
const components = [Button, ButtonGroup]
export { Button, ButtonGroup }
export default {
install(app) {
components.forEach(c => app.component(c.name, c)) // 全局注册
},
}
配合构建工具的 Tree Shaking,未用到的组件不会被打进业务包;再借助 Vite 的插件(如 unplugin-vue-components)即可做到”模板里用哪个就自动打包哪个”。注意在 package.json 里配置 sideEffects: false 与 sideEffects: ['*.css'],并把样式文件单独导出,才能让按需加载真正生效。
库构建与发布
用 Vite 的库模式构建,把 vue 标记为外部依赖(external),避免把 Vue 运行时重复打包进产物:
// vite.config.js
export default {
build: {
lib: { entry: 'src/index.js', name: 'VUI', fileName: 'v-ui' },
rollupOptions: {
external: ['vue'],
output: { globals: { vue: 'Vue' } },
},
},
}
产物 npm publish 前记得在 package.json 配好 main / module / types(TypeScript 类型声明)与 files 字段。组件库若用 TS,推荐 defineProps 的泛型写法获得更精确的 props 类型推导。
再往下:Form 校验、Dialog 与 Table 的设计要点
Button 走通之后,组件库通常会向复杂组件延伸,思路是相通的:
- Form 校验:用
provide把FormItem的校验规则收集起来,Form在提交时统一触发;每个FormItem监听自身prop变化,失焦或输入时调用async-validator这类校验器并把错误信息回显到视图。 - Dialog:用
Teleport把弹窗内容挂到 body,v-model控制visible;配合before-close钩子做关闭前拦截,destroy-on-close控制关闭时是否销毁内容。 - Table:把列配置抽成
columnsprop,内部用v-for渲染表头与单元格;排序、筛选都通过事件上抛,把”数据怎么变”交还给业务层,组件只负责展示。
TypeScript 支持与发布配置
现代组件库几乎都用 TS。在 <script setup lang="ts"> 里用泛型写法定义 props,类型推导更精确:
<script setup lang="ts">
const props = defineProps<{ type?: 'primary' | 'success' | 'danger'; size?: 'lg' | 'sm' }>()
const emit = defineEmits<{ (e: 'click', ev: MouseEvent): void }>()
</script>
发布时 package.json 至少要配这些字段:
{
"main": "dist/v-ui.umd.js",
"module": "dist/v-ui.esm.js",
"types": "dist/index.d.ts",
"sideEffects": ["**/*.css"],
"files": ["dist"]
}
组件库设计原则:Props 与事件怎么定
写业务组件和写组件库组件,最大的区别在”接口设计”。Props 要做到三点:命名语义化(type 而不是 kind,全库统一)、给默认值(default: 'default',让调用方零配置也能用)、用对象类型声明做校验(type: String, validator: v => ['a','b'].includes(v))。事件命名用短横线 update:model-value,与 Vue 约定一致,这样 v-model、.sync 之类的语法糖才能自动接上。样式上坚持”组件不强制布局”,外边距、对齐交给调用方,组件只管自身内部,否则复用起来处处打架。
学习路线导读
按课程视频顺序,建议这样学:
- 第1~6节:搭好 monorepo 工作区与演示项目,理解组件库与文档站如何共处一个仓库;
- 第7~14节:吃透 BEM 命名与 Sass 变量,这是后面所有组件样式的地基;
- 第15~33节:实现 Button 的每一个属性——建议每学一个属性,先自己写一版再对照视频,尤其是
loading、slot、ButtonGroup属性优先级这几个难点; - 第34~48节:进入主题体系,把硬编码颜色全部换成 CSS 变量,尝试二次修改主题色看整套组件如何联动。
常见问题 FAQ
- Q:scoped 样式还会污染吗? 组件库对外暴露的样式通常不用 scoped,而是靠 BEM 命名空间
v-来防冲突;scoped 适合业务组件,库级样式更需可控。 - Q:
v-model在组件库怎么做? 用modelValueprop +update:modelValue事件即可,TextInput 类组件都遵循这套约定。 - Q:为什么按需引入了样式还是没生效? 多半是没有引入对应的 css 文件,或
sideEffects配错导致样式被 Tree Shaking 干掉了。
总结
学组件库不是”抄一个 Button”,而是把 Vue3 响应式、组件通信、样式体系、构建发布这条链路走一遍。课程以 Button 为切入口,把 monorepo、BEM、Sass 主题、全局/按需注册这些组件库”骨架”知识讲透,动手写完后再去读 Element Plus 这类开源库的源码,会顺畅很多。
📁 目录结构
目录概览
- 📂 课件(48 节视频,按模块组织)
📋 点击展开查看瘦身后的章节大纲
[V2]Vue.js 3高级编程:UI组件库开发/
└── 📁 课件/
├── 工作区与项目搭建(第1~6节)
│ ├── monorepo 建立工作区、构建演示项目
│ └── button 组件目录、全局注册 / 按需加载
├── CSS 命名与 Sass 体系(第7~14节)
│ ├── CSS 元素规范、BEM 命名、命名空间
│ └── sass block / element / modifier / is 状态类
├── Button 组件属性实现(第15~33节)
│ ├── 基础渲染、theme、round、disabled、hover
│ ├── text / link / block / border / size / circle / icon
│ ├── loading(普通与业务加载)、click 事件、slot 插槽
│ └── ButtonGroup 组件样式与属性优先级
└── Sass 主题体系(第34~49节)
├── deepMerge 定义主题色、层次色生成原理
├── @each @for @include 生成层色、root 变量前缀
└── 生成主题色/层次色/全局变量属性、Button 绑定主题色
资源获取
💡 建议:尽快保存到本地网盘或电脑,避免分享链接后期失效。
整理不易,如果对你有帮助,欢迎分享给更多需要的朋友。













请登录后查看评论内容