7.1 组件化开发概述
7.1.1 什么是组件化开发
组件化开发是一种将 UI 拆分为独立、可复用的代码片段的开发方法。每个组件封装了自己的结构、样式和行为,可以在应用程序的不同部分重复使用。
7.1.2 组件化的优势
- 可复用性:一次编写,多处使用
- 可维护性:集中管理,易于修改
- 一致性:确保 UI 的统一性
- 开发效率:减少重复代码
- 团队协作:便于分工合作
7.1.3 Tailwind CSS 中的组件化方法
在 Tailwind CSS 中,我们可以通过以下方式实现组件化:
- HTML 模板组件
- CSS 组件类
- JavaScript 框架组件(React、Vue、Angular 等)
- Web Components
7.2 使用 @apply 指令创建组件类
7.2.1 @apply 指令基础
@apply
指令允许我们将 Tailwind 的工具类组合成自定义的 CSS 类:
/* styles.css */
.btn {
@apply px-4 py-2 rounded font-medium focus:outline-none focus:ring-2 focus:ring-offset-2;
}
.btn-primary {
@apply bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500;
}
.btn-secondary {
@apply bg-gray-600 text-white hover:bg-gray-700 focus:ring-gray-500;
}
.btn-success {
@apply bg-green-600 text-white hover:bg-green-700 focus:ring-green-500;
}
.btn-danger {
@apply bg-red-600 text-white hover:bg-red-700 focus:ring-red-500;
}
7.2.2 按钮组件示例
<!-- 使用组件类 -->
<button class="btn btn-primary">主要按钮</button>
<button class="btn btn-secondary">次要按钮</button>
<button class="btn btn-success">成功按钮</button>
<button class="btn btn-danger">危险按钮</button>
<!-- 不同尺寸的按钮 -->
<style>
.btn-sm {
@apply px-3 py-1.5 text-sm;
}
.btn-lg {
@apply px-6 py-3 text-lg;
}
.btn-xl {
@apply px-8 py-4 text-xl;
}
</style>
<button class="btn btn-primary btn-sm">小按钮</button>
<button class="btn btn-primary">默认按钮</button>
<button class="btn btn-primary btn-lg">大按钮</button>
<button class="btn btn-primary btn-xl">超大按钮</button>
7.2.3 卡片组件示例
/* 基础卡片 */
.card {
@apply bg-white rounded-lg shadow-md overflow-hidden;
}
.card-header {
@apply px-6 py-4 border-b border-gray-200;
}
.card-body {
@apply px-6 py-4;
}
.card-footer {
@apply px-6 py-4 bg-gray-50 border-t border-gray-200;
}
/* 卡片变体 */
.card-elevated {
@apply shadow-lg hover:shadow-xl transition-shadow duration-300;
}
.card-bordered {
@apply border border-gray-200 shadow-sm;
}
.card-flat {
@apply shadow-none border border-gray-200;
}
<!-- 基础卡片 -->
<div class="card">
<div class="card-header">
<h3 class="text-lg font-semibold text-gray-900">卡片标题</h3>
</div>
<div class="card-body">
<p class="text-gray-600">这是卡片的内容区域,可以包含任何类型的内容。</p>
</div>
<div class="card-footer">
<button class="btn btn-primary">操作按钮</button>
</div>
</div>
<!-- 高级卡片 -->
<div class="card card-elevated">
<div class="card-body">
<h3 class="text-xl font-bold text-gray-900 mb-2">产品名称</h3>
<p class="text-gray-600 mb-4">产品描述信息...</p>
<div class="flex justify-between items-center">
<span class="text-2xl font-bold text-blue-600">¥299</span>
<button class="btn btn-primary">立即购买</button>
</div>
</div>
</div>
7.3 表单组件库
7.3.1 输入框组件
/* 基础输入框 */
.form-input {
@apply w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent;
}
.form-input-sm {
@apply px-2 py-1 text-sm;
}
.form-input-lg {
@apply px-4 py-3 text-lg;
}
/* 输入框状态 */
.form-input-error {
@apply border-red-500 focus:ring-red-500;
}
.form-input-success {
@apply border-green-500 focus:ring-green-500;
}
/* 标签 */
.form-label {
@apply block text-sm font-medium text-gray-700 mb-1;
}
.form-label-required::after {
content: ' *';
@apply text-red-500;
}
/* 帮助文本 */
.form-help {
@apply text-sm text-gray-500 mt-1;
}
.form-error {
@apply text-sm text-red-600 mt-1;
}
/* 表单组 */
.form-group {
@apply mb-4;
}
<!-- 基础表单组件 -->
<div class="form-group">
<label for="email" class="form-label form-label-required">邮箱地址</label>
<input type="email" id="email" class="form-input" placeholder="请输入邮箱地址">
<p class="form-help">我们不会与任何人分享您的邮箱地址</p>
</div>
<!-- 错误状态 -->
<div class="form-group">
<label for="password" class="form-label form-label-required">密码</label>
<input type="password" id="password" class="form-input form-input-error" placeholder="请输入密码">
<p class="form-error">密码长度至少为 8 个字符</p>
</div>
<!-- 成功状态 -->
<div class="form-group">
<label for="username" class="form-label">用户名</label>
<input type="text" id="username" class="form-input form-input-success" placeholder="请输入用户名">
<p class="form-help text-green-600">用户名可用</p>
</div>
7.3.2 选择框组件
/* 选择框 */
.form-select {
@apply w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white;
}
/* 复选框和单选框 */
.form-checkbox,
.form-radio {
@apply w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500;
}
.form-radio {
@apply rounded-full;
}
.form-check {
@apply flex items-center;
}
.form-check-label {
@apply ml-2 text-sm text-gray-700;
}
.form-check-group {
@apply space-y-2;
}
<!-- 选择框 -->
<div class="form-group">
<label for="country" class="form-label">国家/地区</label>
<select id="country" class="form-select">
<option value="">请选择国家/地区</option>
<option value="cn">中国</option>
<option value="us">美国</option>
<option value="jp">日本</option>
</select>
</div>
<!-- 复选框组 -->
<div class="form-group">
<label class="form-label">兴趣爱好</label>
<div class="form-check-group">
<div class="form-check">
<input type="checkbox" id="reading" class="form-checkbox">
<label for="reading" class="form-check-label">阅读</label>
</div>
<div class="form-check">
<input type="checkbox" id="music" class="form-checkbox">
<label for="music" class="form-check-label">音乐</label>
</div>
<div class="form-check">
<input type="checkbox" id="sports" class="form-checkbox">
<label for="sports" class="form-check-label">运动</label>
</div>
</div>
</div>
<!-- 单选框组 -->
<div class="form-group">
<label class="form-label">性别</label>
<div class="form-check-group">
<div class="form-check">
<input type="radio" id="male" name="gender" class="form-radio">
<label for="male" class="form-check-label">男</label>
</div>
<div class="form-check">
<input type="radio" id="female" name="gender" class="form-radio">
<label for="female" class="form-check-label">女</label>
</div>
</div>
</div>
7.4 导航组件库
7.4.1 导航栏组件
/* 基础导航栏 */
.navbar {
@apply bg-white shadow-sm border-b border-gray-200;
}
.navbar-container {
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
}
.navbar-content {
@apply flex justify-between items-center h-16;
}
.navbar-brand {
@apply flex items-center;
}
.navbar-logo {
@apply w-8 h-8 mr-3;
}
.navbar-title {
@apply text-xl font-bold text-gray-900;
}
.navbar-nav {
@apply hidden md:flex items-center space-x-8;
}
.navbar-link {
@apply text-gray-600 hover:text-blue-600 px-3 py-2 rounded-md text-sm font-medium transition-colors;
}
.navbar-link-active {
@apply text-blue-600 bg-blue-50;
}
.navbar-toggle {
@apply md:hidden text-gray-600 hover:text-blue-600;
}
<!-- 导航栏组件 -->
<nav class="navbar">
<div class="navbar-container">
<div class="navbar-content">
<!-- 品牌 -->
<div class="navbar-brand">
<div class="navbar-logo bg-blue-600 rounded"></div>
<span class="navbar-title">品牌名</span>
</div>
<!-- 导航链接 -->
<div class="navbar-nav">
<a href="#" class="navbar-link navbar-link-active">首页</a>
<a href="#" class="navbar-link">产品</a>
<a href="#" class="navbar-link">服务</a>
<a href="#" class="navbar-link">关于</a>
<button class="btn btn-primary">联系我们</button>
</div>
<!-- 移动端菜单按钮 -->
<button class="navbar-toggle">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
</div>
</nav>
7.4.2 面包屑组件
.breadcrumb {
@apply flex items-center space-x-2 text-sm text-gray-500;
}
.breadcrumb-item {
@apply flex items-center;
}
.breadcrumb-link {
@apply hover:text-blue-600 transition-colors;
}
.breadcrumb-current {
@apply text-gray-900 font-medium;
}
.breadcrumb-separator {
@apply mx-2 text-gray-400;
}
<!-- 面包屑组件 -->
<nav class="breadcrumb">
<div class="breadcrumb-item">
<a href="#" class="breadcrumb-link">首页</a>
</div>
<div class="breadcrumb-separator">/</div>
<div class="breadcrumb-item">
<a href="#" class="breadcrumb-link">产品</a>
</div>
<div class="breadcrumb-separator">/</div>
<div class="breadcrumb-item">
<span class="breadcrumb-current">详情</span>
</div>
</nav>
7.4.3 标签页组件
.tabs {
@apply border-b border-gray-200;
}
.tabs-nav {
@apply flex space-x-8;
}
.tabs-tab {
@apply py-2 px-1 border-b-2 border-transparent text-sm font-medium text-gray-500 hover:text-gray-700 hover:border-gray-300 transition-colors;
}
.tabs-tab-active {
@apply border-blue-500 text-blue-600;
}
.tabs-content {
@apply py-4;
}
.tabs-panel {
@apply hidden;
}
.tabs-panel-active {
@apply block;
}
<!-- 标签页组件 -->
<div class="tabs">
<nav class="tabs-nav">
<button class="tabs-tab tabs-tab-active">概述</button>
<button class="tabs-tab">规格</button>
<button class="tabs-tab">评价</button>
<button class="tabs-tab">支持</button>
</nav>
</div>
<div class="tabs-content">
<div class="tabs-panel tabs-panel-active">
<h3 class="text-lg font-semibold mb-2">产品概述</h3>
<p class="text-gray-600">这里是产品的详细概述信息...</p>
</div>
<div class="tabs-panel">
<h3 class="text-lg font-semibold mb-2">技术规格</h3>
<p class="text-gray-600">这里是产品的技术规格信息...</p>
</div>
<div class="tabs-panel">
<h3 class="text-lg font-semibold mb-2">用户评价</h3>
<p class="text-gray-600">这里是用户评价信息...</p>
</div>
<div class="tabs-panel">
<h3 class="text-lg font-semibold mb-2">技术支持</h3>
<p class="text-gray-600">这里是技术支持信息...</p>
</div>
</div>
7.5 反馈组件库
7.5.1 警告框组件
/* 基础警告框 */
.alert {
@apply p-4 rounded-md border;
}
.alert-info {
@apply bg-blue-50 border-blue-200 text-blue-800;
}
.alert-success {
@apply bg-green-50 border-green-200 text-green-800;
}
.alert-warning {
@apply bg-yellow-50 border-yellow-200 text-yellow-800;
}
.alert-error {
@apply bg-red-50 border-red-200 text-red-800;
}
.alert-title {
@apply font-medium mb-1;
}
.alert-description {
@apply text-sm opacity-90;
}
.alert-close {
@apply float-right text-lg leading-none cursor-pointer opacity-50 hover:opacity-75;
}
<!-- 警告框组件 -->
<div class="alert alert-info">
<button class="alert-close">×</button>
<div class="alert-title">信息提示</div>
<div class="alert-description">这是一条信息提示消息。</div>
</div>
<div class="alert alert-success">
<div class="alert-title">操作成功</div>
<div class="alert-description">您的操作已成功完成。</div>
</div>
<div class="alert alert-warning">
<div class="alert-title">注意</div>
<div class="alert-description">请注意这个重要信息。</div>
</div>
<div class="alert alert-error">
<div class="alert-title">错误</div>
<div class="alert-description">操作失败,请重试。</div>
</div>
7.5.2 徽章组件
.badge {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
}
.badge-primary {
@apply bg-blue-100 text-blue-800;
}
.badge-secondary {
@apply bg-gray-100 text-gray-800;
}
.badge-success {
@apply bg-green-100 text-green-800;
}
.badge-warning {
@apply bg-yellow-100 text-yellow-800;
}
.badge-danger {
@apply bg-red-100 text-red-800;
}
.badge-lg {
@apply px-3 py-1 text-sm;
}
.badge-dot {
@apply w-2 h-2 rounded-full mr-1.5;
}
<!-- 徽章组件 -->
<span class="badge badge-primary">新功能</span>
<span class="badge badge-success">已完成</span>
<span class="badge badge-warning">待处理</span>
<span class="badge badge-danger">紧急</span>
<!-- 带点的徽章 -->
<span class="badge badge-primary">
<span class="badge-dot bg-blue-400"></span>
在线
</span>
<!-- 大尺寸徽章 -->
<span class="badge badge-success badge-lg">推荐</span>
7.5.3 进度条组件
.progress {
@apply w-full bg-gray-200 rounded-full overflow-hidden;
}
.progress-bar {
@apply h-2 bg-blue-600 transition-all duration-300 ease-out;
}
.progress-sm .progress-bar {
@apply h-1;
}
.progress-lg .progress-bar {
@apply h-4;
}
.progress-bar-success {
@apply bg-green-600;
}
.progress-bar-warning {
@apply bg-yellow-600;
}
.progress-bar-danger {
@apply bg-red-600;
}
.progress-label {
@apply text-sm text-gray-600 mb-1;
}
.progress-percentage {
@apply text-sm text-gray-600 float-right;
}
<!-- 进度条组件 -->
<div class="mb-4">
<div class="progress-label">
项目进度
<span class="progress-percentage">75%</span>
</div>
<div class="progress">
<div class="progress-bar" style="width: 75%"></div>
</div>
</div>
<!-- 不同颜色的进度条 -->
<div class="mb-4">
<div class="progress-label">成功进度</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 90%"></div>
</div>
</div>
<div class="mb-4">
<div class="progress-label">警告进度</div>
<div class="progress">
<div class="progress-bar progress-bar-warning" style="width: 60%"></div>
</div>
</div>
<!-- 不同尺寸的进度条 -->
<div class="mb-4">
<div class="progress-label">小进度条</div>
<div class="progress progress-sm">
<div class="progress-bar" style="width: 45%"></div>
</div>
</div>
<div class="mb-4">
<div class="progress-label">大进度条</div>
<div class="progress progress-lg">
<div class="progress-bar" style="width: 80%"></div>
</div>
</div>
7.6 布局组件库
7.6.1 容器组件
.container-fluid {
@apply w-full px-4 sm:px-6 lg:px-8;
}
.container-sm {
@apply max-w-sm mx-auto px-4;
}
.container-md {
@apply max-w-md mx-auto px-4;
}
.container-lg {
@apply max-w-lg mx-auto px-4;
}
.container-xl {
@apply max-w-xl mx-auto px-4;
}
.container-2xl {
@apply max-w-2xl mx-auto px-4;
}
.container-full {
@apply max-w-full mx-auto px-4;
}
7.6.2 网格组件
.grid-container {
@apply grid gap-4;
}
.grid-cols-auto {
@apply grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4;
}
.grid-cols-responsive {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
@apply bg-white rounded-lg shadow-sm p-4;
}
7.6.3 分隔符组件
.divider {
@apply border-t border-gray-200 my-4;
}
.divider-vertical {
@apply border-l border-gray-200 mx-4 h-full;
}
.divider-text {
@apply relative flex justify-center my-4;
}
.divider-text::before {
content: '';
@apply absolute top-1/2 left-0 right-0 border-t border-gray-200;
}
.divider-text span {
@apply bg-white px-4 text-sm text-gray-500;
}
<!-- 分隔符组件 -->
<div class="divider"></div>
<div class="divider-text">
<span>或者</span>
</div>
<!-- 垂直分隔符 -->
<div class="flex items-center h-12">
<span>左侧内容</span>
<div class="divider-vertical"></div>
<span>右侧内容</span>
</div>
7.7 实践案例:构建组件库
7.7.1 创建组件库结构
components/
├── base/
│ ├── buttons.css
│ ├── forms.css
│ └── typography.css
├── layout/
│ ├── containers.css
│ ├── grid.css
│ └── dividers.css
├── navigation/
│ ├── navbar.css
│ ├── breadcrumb.css
│ └── tabs.css
├── feedback/
│ ├── alerts.css
│ ├── badges.css
│ └── progress.css
└── components.css
7.7.2 主组件文件
/* components/components.css */
@import './base/buttons.css';
@import './base/forms.css';
@import './base/typography.css';
@import './layout/containers.css';
@import './layout/grid.css';
@import './layout/dividers.css';
@import './navigation/navbar.css';
@import './navigation/breadcrumb.css';
@import './navigation/tabs.css';
@import './feedback/alerts.css';
@import './feedback/badges.css';
@import './feedback/progress.css';
7.7.3 组件文档页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件库文档</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="components/components.css">
</head>
<body class="bg-gray-50">
<!-- 导航栏 -->
<nav class="navbar">
<div class="navbar-container">
<div class="navbar-content">
<div class="navbar-brand">
<div class="navbar-logo bg-blue-600 rounded"></div>
<span class="navbar-title">组件库</span>
</div>
<div class="navbar-nav">
<a href="#buttons" class="navbar-link">按钮</a>
<a href="#forms" class="navbar-link">表单</a>
<a href="#navigation" class="navbar-link">导航</a>
<a href="#feedback" class="navbar-link">反馈</a>
</div>
</div>
</div>
</nav>
<!-- 主要内容 -->
<main class="container-fluid py-8">
<div class="max-w-6xl mx-auto">
<!-- 按钮组件 -->
<section id="buttons" class="mb-12">
<h2 class="text-2xl font-bold text-gray-900 mb-6">按钮组件</h2>
<div class="card mb-6">
<div class="card-header">
<h3 class="text-lg font-semibold">基础按钮</h3>
</div>
<div class="card-body">
<div class="flex flex-wrap gap-4 mb-4">
<button class="btn btn-primary">主要按钮</button>
<button class="btn btn-secondary">次要按钮</button>
<button class="btn btn-success">成功按钮</button>
<button class="btn btn-danger">危险按钮</button>
</div>
<pre class="bg-gray-100 p-4 rounded text-sm overflow-x-auto"><code><button class="btn btn-primary">主要按钮</button>
<button class="btn btn-secondary">次要按钮</button>
<button class="btn btn-success">成功按钮</button>
<button class="btn btn-danger">危险按钮</button></code></pre>
</div>
</div>
<div class="card mb-6">
<div class="card-header">
<h3 class="text-lg font-semibold">按钮尺寸</h3>
</div>
<div class="card-body">
<div class="flex flex-wrap items-center gap-4 mb-4">
<button class="btn btn-primary btn-sm">小按钮</button>
<button class="btn btn-primary">默认按钮</button>
<button class="btn btn-primary btn-lg">大按钮</button>
<button class="btn btn-primary btn-xl">超大按钮</button>
</div>
<pre class="bg-gray-100 p-4 rounded text-sm overflow-x-auto"><code><button class="btn btn-primary btn-sm">小按钮</button>
<button class="btn btn-primary">默认按钮</button>
<button class="btn btn-primary btn-lg">大按钮</button>
<button class="btn btn-primary btn-xl">超大按钮</button></code></pre>
</div>
</div>
</section>
<!-- 表单组件 -->
<section id="forms" class="mb-12">
<h2 class="text-2xl font-bold text-gray-900 mb-6">表单组件</h2>
<div class="card mb-6">
<div class="card-header">
<h3 class="text-lg font-semibold">输入框</h3>
</div>
<div class="card-body">
<div class="max-w-md">
<div class="form-group">
<label for="demo-input" class="form-label">标签</label>
<input type="text" id="demo-input" class="form-input" placeholder="请输入内容">
<p class="form-help">这是帮助文本</p>
</div>
<div class="form-group">
<label for="demo-error" class="form-label">错误状态</label>
<input type="text" id="demo-error" class="form-input form-input-error" placeholder="错误输入">
<p class="form-error">这是错误信息</p>
</div>
</div>
</div>
</div>
</section>
<!-- 反馈组件 -->
<section id="feedback" class="mb-12">
<h2 class="text-2xl font-bold text-gray-900 mb-6">反馈组件</h2>
<div class="card mb-6">
<div class="card-header">
<h3 class="text-lg font-semibold">警告框</h3>
</div>
<div class="card-body space-y-4">
<div class="alert alert-info">
<div class="alert-title">信息提示</div>
<div class="alert-description">这是一条信息提示消息。</div>
</div>
<div class="alert alert-success">
<div class="alert-title">操作成功</div>
<div class="alert-description">您的操作已成功完成。</div>
</div>
<div class="alert alert-warning">
<div class="alert-title">注意</div>
<div class="alert-description">请注意这个重要信息。</div>
</div>
<div class="alert alert-error">
<div class="alert-title">错误</div>
<div class="alert-description">操作失败,请重试。</div>
</div>
</div>
</div>
<div class="card mb-6">
<div class="card-header">
<h3 class="text-lg font-semibold">徽章</h3>
</div>
<div class="card-body">
<div class="flex flex-wrap gap-2 mb-4">
<span class="badge badge-primary">主要</span>
<span class="badge badge-secondary">次要</span>
<span class="badge badge-success">成功</span>
<span class="badge badge-warning">警告</span>
<span class="badge badge-danger">危险</span>
</div>
</div>
</div>
</section>
</div>
</main>
</body>
</html>
7.8 组件化最佳实践
7.8.1 设计原则
- 一致性:保持设计和行为的一致性
- 可复用性:组件应该易于在不同场景中使用
- 可扩展性:支持通过修饰符类扩展功能
- 可访问性:确保组件符合无障碍访问标准
- 性能:避免不必要的样式重复
7.8.2 命名规范
- BEM 方法论:Block__Element–Modifier
- 语义化命名:使用有意义的类名
- 前缀约定:为组件添加统一前缀
/* 好的命名示例 */
.btn { /* Block */ }
.btn__icon { /* Element */ }
.btn--large { /* Modifier */ }
.btn--primary { /* Modifier */ }
/* 避免的命名 */
.blue-button { /* 过于具体 */ }
.big { /* 过于通用 */ }
.btn1 { /* 无意义 */ }
7.8.3 文档化
- 使用示例:提供清晰的使用示例
- 参数说明:说明可用的修饰符和选项
- 设计指南:说明何时使用该组件
- 可访问性说明:提供无障碍访问指导
7.8.4 测试策略
- 视觉回归测试:确保组件外观一致
- 功能测试:验证组件行为正确
- 可访问性测试:检查无障碍访问支持
- 性能测试:监控组件性能影响
7.9 本章总结
在本章中,我们学习了组件化开发的核心概念和实践:
核心要点
- 组件化概念:理解组件化开发的优势和方法
- @apply 指令:使用 @apply 创建可复用的组件类
- 组件库构建:创建完整的 UI 组件库
- 最佳实践:遵循设计原则和命名规范
- 文档化:为组件提供完整的文档
最佳实践
- 保持组件的一致性和可复用性
- 使用语义化的命名规范
- 提供完整的文档和示例
- 注重可访问性和性能
下一步
在下一章中,我们将学习动画与过渡效果,了解如何为组件添加动态效果。
7.10 练习题
- 按钮组件练习:创建一个完整的按钮组件系统,包括不同状态、尺寸和样式
- 表单组件练习:构建一套表单组件,包括验证状态和帮助文本
- 卡片组件练习:设计一个灵活的卡片组件,支持不同的内容布局
练习提示
- 使用 @apply 指令创建组件类
- 考虑组件的可扩展性和复用性
- 为组件编写使用文档
- 测试组件在不同场景下的表现