Skip to content

使用场景与最佳实践

Lerna Web UI 组件库专为各种前端应用场景设计,从简单的单页应用到复杂的企业级系统都能胜任。以下是详细的使用场景和最佳实践指南。

🎯 适用场景

1. 中后台管理系统

适用于企业级后台、Admin Dashboard、数据管理平台等。

典型特征

  • 大量表单输入和数据录入
  • 复杂的表格和列表展示
  • 多变的交互状态(加载、禁用、错误等)
  • 需要统一的设计规范和主题定制

示例:用户管理表单

<template>
  <div class="user-form">
    <h2>用户信息</h2>
    
    <div class="form-item">
      <label>用户名</label>
      <Input 
        v-model="username" 
        placeholder="请输入用户名"
        size="large"
      />
    </div>
    
    <div class="form-item">
      <label>邮箱</label>
      <Input 
        v-model="email" 
        type="email"
        placeholder="请输入邮箱"
        :error="!isValidEmail"
      />
    </div>
    
    <div class="form-actions">
      <Button 
        type="primary" 
        size="large"
        @click="handleSubmit"
        :loading="isSubmitting"
      >
        提交
      </Button>
      <Button 
        size="large"
        @click="handleReset"
      >
        重置
      </Button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { Button, Input } from '@lerna-web-ui/ui'

const username = ref('')
const email = ref('')
const isSubmitting = ref(false)

const isValidEmail = computed(() => {
  return !email.value || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)
})

const handleSubmit = async () => {
  if (!isValidEmail.value) return
  
  isSubmitting.value = true
  try {
    // 模拟 API 调用
    await new Promise(resolve => setTimeout(resolve, 2000))
    console.log('提交成功', { username: username.value, email: email.value })
  } finally {
    isSubmitting.value = false
  }
}

const handleReset = () => {
  username.value = ''
  email.value = ''
}
</script>

<style scoped>
.user-form {
  max-width: 500px;
  padding: 24px;
}

.form-item {
  margin-bottom: 16px;
}

.form-item label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
}

.form-actions {
  display: flex;
  gap: 12px;
  margin-top: 24px;
}
</style>

2. 数据可视化仪表板

适用于数据分析平台、监控面板、业务报表等。

示例:数据筛选工具栏

<template>
  <div class="dashboard-toolbar">
    <div class="filters">
      <Input 
        v-model="searchQuery"
        placeholder="搜索..."
        size="small"
      />
      
      <Button 
        type="primary" 
        size="small"
        @click="handleSearch"
      >
        搜索
      </Button>
      
      <Button 
        size="small"
        @click="handleExport"
      >
        导出
      </Button>
    </div>
    
    <div class="actions">
      <Button 
        type="success"
        size="small"
        @click="handleRefresh"
      >
        刷新
      </Button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Button, Input } from '@lerna-web-ui/ui'

const searchQuery = ref('')

const handleSearch = () => {
  console.log('搜索:', searchQuery.value)
}

const handleExport = () => {
  console.log('导出数据')
}

const handleRefresh = () => {
  console.log('刷新数据')
}
</script>

<style scoped>
.dashboard-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background: var(--lerna-bg-color-secondary);
  border-radius: var(--lerna-radius-md);
  margin-bottom: 24px;
}

.filters {
  display: flex;
  gap: 12px;
  align-items: center;
}

.actions {
  display: flex;
  gap: 8px;
}
</style>

3. 电商应用

适用于商品管理、订单处理、购物车等场景。

示例:商品操作按钮组

<template>
  <div class="product-actions">
    <Button 
      type="primary"
      block
      @click="addToCart"
    >
      加入购物车
    </Button>
    
    <div class="action-row">
      <Button 
        type="danger"
        size="small"
        @click="buyNow"
      >
        立即购买
      </Button>
      
      <Button 
        size="small"
        @click="addToWishlist"
      >
        <template #icon>❤️</template>
        收藏
      </Button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { Button } from '@lerna-web-ui/ui'

const addToCart = () => {
  console.log('加入购物车')
}

const buyNow = () => {
  console.log('立即购买')
}

const addToWishlist = () => {
  console.log('添加到收藏夹')
}
</script>

<style scoped>
.product-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.action-row {
  display: flex;
  gap: 8px;
}
</style>

4. SaaS 应用

适用于订阅管理、设置页面、用户配置等。

示例:设置页面表单

<template>
  <div class="settings-panel">
    <section class="settings-section">
      <h3>账户设置</h3>
      
      <div class="setting-item">
        <label>显示名称</label>
        <Input 
          v-model="displayName"
          placeholder="您的显示名称"
        />
      </div>
      
      <div class="setting-item">
        <label>通知邮箱</label>
        <Input 
          v-model="notificationEmail"
          type="email"
          placeholder="接收通知的邮箱地址"
        />
      </div>
      
      <div class="setting-actions">
        <Button 
          type="primary"
          @click="saveSettings"
        >
          保存设置
        </Button>
        <Button 
          @click="resetSettings"
        >
          重置
        </Button>
      </div>
    </section>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Button, Input } from '@lerna-web-ui/ui'

const displayName = ref('')
const notificationEmail = ref('')

const saveSettings = () => {
  console.log('保存设置')
}

const resetSettings = () => {
  displayName.value = ''
  notificationEmail.value = ''
}
</script>

<style scoped>
.settings-panel {
  max-width: 600px;
  padding: 24px;
}

.settings-section {
  margin-bottom: 32px;
}

.setting-item {
  margin-bottom: 16px;
}

.setting-item label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
  color: var(--lerna-text-color);
}

.setting-actions {
  display: flex;
  gap: 12px;
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--lerna-border-color);
}
</style>

🔧 高级用法

1. 表单验证组合

结合多个组件实现完整的表单验证流程。

<template>
  <form @submit.prevent="handleSubmit" class="validated-form">
    <div class="form-field">
      <label>用户名</label>
      <Input 
        v-model="formData.username"
        :error="errors.username"
        placeholder="至少 3 个字符"
      />
      <span v-if="errors.username" class="error-message">
        {{ errors.username }}
      </span>
    </div>
    
    <div class="form-field">
      <label>密码</label>
      <Input 
        v-model="formData.password"
        type="password"
        :error="errors.password"
        placeholder="至少 6 个字符"
      />
      <span v-if="errors.password" class="error-message">
        {{ errors.password }}
      </span>
    </div>
    
    <Button 
      type="primary"
      type="submit"
      :loading="isLoading"
      :disabled="!canSubmit"
      block
    >
      登录
    </Button>
  </form>
</template>

<script setup lang="ts">
import { ref, computed, reactive } from 'vue'
import { Button, Input } from '@lerna-web-ui/ui'

const formData = reactive({
  username: '',
  password: ''
})

const errors = reactive({
  username: '',
  password: ''
})

const isLoading = ref(false)

const canSubmit = computed(() => {
  return formData.username.length >= 3 && 
         formData.password.length >= 6
})

const validate = () => {
  errors.username = ''
  errors.password = ''
  
  if (formData.username.length < 3) {
    errors.username = '用户名至少 3 个字符'
    return false
  }
  
  if (formData.password.length < 6) {
    errors.password = '密码至少 6 个字符'
    return false
  }
  
  return true
}

const handleSubmit = async () => {
  if (!validate()) return
  
  isLoading.value = true
  try {
    // 模拟 API 调用
    await new Promise(resolve => setTimeout(resolve, 1500))
    console.log('登录成功')
  } finally {
    isLoading.value = false
  }
}
</script>

<style scoped>
.validated-form {
  max-width: 400px;
}

.form-field {
  margin-bottom: 16px;
}

.form-field label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
}

.error-message {
  display: block;
  margin-top: 4px;
  color: var(--lerna-color-danger);
  font-size: var(--lerna-font-size-sm);
}
</style>

2. 响应式布局

适配不同屏幕尺寸的响应式设计。

<template>
  <div class="responsive-container">
    <div class="toolbar">
      <Input 
        v-model="search"
        placeholder="搜索内容..."
        class="search-input"
      />
      
      <div class="button-group">
        <Button 
          type="primary"
          size="small"
          @click="handleAction1"
        >
          操作 1
        </Button>
        <Button 
          size="small"
          @click="handleAction2"
        >
          操作 2
        </Button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Button, Input } from '@lerna-web-ui/ui'

const search = ref('')

const handleAction1 = () => {
  console.log('执行操作 1')
}

const handleAction2 = () => {
  console.log('执行操作 2')
}
</script>

<style scoped>
.responsive-container {
  width: 100%;
  padding: 16px;
}

.toolbar {
  display: flex;
  gap: 16px;
  align-items: center;
}

.search-input {
  flex: 1;
  min-width: 200px;
}

.button-group {
  display: flex;
  gap: 8px;
}

/* 移动端适配 */
@media (max-width: 768px) {
  .toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  
  .search-input {
    width: 100%;
  }
  
  .button-group {
    justify-content: stretch;
  }
  
  .button-group button {
    flex: 1;
  }
}
</style>

## 📊 性能优化

### 1. 按需加载与 Tree Shaking

组件库支持 Tree Shaking,建议直接导入需要的组件:

```ts
// ✅ 推荐:按需导入
import { Button, Input } from '@lerna-web-ui/ui'

// ❌ 不推荐:全量导入
import LernaWebUI from '@lerna-web-ui/ui'

如果使用 Vite,可以配置 optimizeDeps 优化依赖预构建:

ts
// vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: {
    include: ['@lerna-web-ui/ui']
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'lerna-web-ui': ['@lerna-web-ui/ui']
        }
      }
    }
  }
})

2. 自动导入配置(可选)

如果需要实现组件自动导入,可以手动配置解析器:

ts
// vite.config.ts
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'

export default defineConfig({
  plugins: [
    Components({
      // 自定义解析器
      resolvers: [
        (name) => {
          if (name === 'Button' || name === 'Input') {
            return {
              name,
              from: '@lerna-web-ui/ui'
            }
          }
        }
      ]
    })
  ]
})

3. 懒加载组件

对于大型应用,可以按需异步加载组件以优化初始加载性能:

``vue

```

注意: 懒加载会增加组件的首次渲染时间,建议仅用于不常用的大型组件。

🎨 设计原则

1. 一致性

保持整个应用的视觉和交互体验一致。

vue
<template>
  <!-- ✅ 好的做法:统一的按钮类型和尺寸 -->
  <div class="button-group">
    <Button type="primary" size="medium">主要操作</Button>
    <Button size="medium">次要操作</Button>
  </div>
  
  <!-- ❌ 避免:混用不同的尺寸和类型 -->
  <div class="button-group">
    <Button type="primary" size="small">小按钮</Button>
    <Button type="danger" size="large">大按钮</Button>
  </div>
</template>

2. 可访问性

确保所有用户都能使用你的应用。

vue
<template>
  <!-- 为图标按钮添加 aria-label -->
  <Button 
    size="small"
    aria-label="关闭对话框"
    @click="closeDialog"
  >

  </Button>
  
  <!-- 为表单字段添加关联标签 -->
  <label for="username">用户名</label>
  <Input id="username" v-model="username" />
</template>

3. 状态反馈

及时响应用户操作,提供清晰的反馈。

vue
<template>
  <Button 
    type="primary"
    :loading="isLoading"
    :disabled="isDisabled"
    @click="handleAction"
  >
    {{ buttonText }}
  </Button>
</template>

<script setup lang="ts">
import { computed } from 'vue'

const isLoading = ref(false)
const isSuccess = ref(false)

const buttonText = computed(() => {
  if (isLoading.value) return '处理中...'
  if (isSuccess.value) return '已完成'
  return '提交'
})
</script>

🚀 最佳实践总结

✅ 推荐做法

  1. 统一尺寸: 在同一界面中使用一致的按钮尺寸
  2. 明确状态: 清晰表达加载、禁用、错误等状态
  3. 语义化类型: 根据操作性质选择合适的按钮类型
  4. 适度使用: 避免过度装饰,保持简洁
  5. 测试验证: 在不同设备和主题下测试组件表现

❌ 避免事项

  1. 混用风格: 不要在同一区域混用多种按钮类型
  2. 忽略状态: 不要忘记处理加载和禁用状态
  3. 过度嵌套: 避免过多的条件渲染和嵌套
  4. 忽视无障碍: 不要忽略 ARIA 属性和键盘导航
  5. 硬编码样式: 优先使用设计令牌而非固定值

📚 相关资源


💡 提示: 以上示例代码可以直接复制使用,建议根据实际业务需求进行调整和优化。

Released under the MIT License.