反馈提示组件设计规范完全指南

HTMLPAGE 团队
18分钟 分钟阅读

系统讲解前端反馈提示组件的设计规范,包括 Toast、Modal、Notification、Alert 等组件的设计原则、使用场景和最佳实践。

#组件设计 #反馈提示 #用户体验 #Toast #Modal

反馈提示组件概述

反馈提示组件用于向用户传达系统状态、操作结果或需要注意的信息。合理使用可以:

  • 降低焦虑 - 让用户知道系统正在响应
  • 确认操作 - 告知操作成功或失败
  • 引导决策 - 提供必要的选择和确认

组件类型与使用场景

组件特点适用场景
Toast轻量、自动消失操作成功/失败提示
Notification可交互、可持续系统通知、消息推送
Alert页面内嵌表单错误、重要提醒
Modal阻断式确认操作、重要决策
Loading状态指示加载中、处理中

Toast 消息组件

设计规范

interface ToastConfig {
  type: 'success' | 'error' | 'warning' | 'info'
  message: string
  duration?: number     // 默认 3000ms
  position?: 'top' | 'bottom' | 'top-right'
  closable?: boolean    // 是否可手动关闭
}

使用原则

适合场景

  • 操作成功/失败的即时反馈
  • 非关键性信息提示
  • 不需要用户确认的通知

设计要点

  • 默认 3 秒自动消失
  • 位置一致,避免用户寻找
  • 同类型消息合并或排队
  • 信息简洁,不超过一行

实现示例

<template>
  <Teleport to="body">
    <TransitionGroup name="toast" tag="div" class="toast-container">
      <div 
        v-for="toast in toasts" 
        :key="toast.id"
        :class="['toast', `toast-${toast.type}`]"
      >
        <component :is="iconMap[toast.type]" class="toast-icon" />
        <span class="toast-message">{{ toast.message }}</span>
        <button v-if="toast.closable" @click="remove(toast.id)">
          <IconClose />
        </button>
      </div>
    </TransitionGroup>
  </Teleport>
</template>

<script setup>
const toasts = ref([])

const show = (config) => {
  const id = Date.now()
  toasts.value.push({ id, ...config })
  
  if (config.duration !== 0) {
    setTimeout(() => remove(id), config.duration || 3000)
  }
}

const remove = (id) => {
  toasts.value = toasts.value.filter(t => t.id !== id)
}

// 暴露给外部使用
defineExpose({ show, remove })
</script>

设计规范

模态框层级

类型z-index用途
基础 Modal1000普通对话框
确认 Modal1010二次确认
全局 Modal1020最高优先级
遮罩层999背景遮罩

使用原则

适合场景

  • 需要用户确认的重要操作
  • 需要专注处理的子任务
  • 复杂表单或流程

设计要点

  • 清晰的标题说明目的
  • 主操作按钮突出显示
  • 提供明确的取消/关闭方式
  • 支持 ESC 键关闭
  • 遮罩层点击可选关闭

确认对话框

<template>
  <Modal v-model="visible">
    <template #header>
      <h3>确认删除</h3>
    </template>
    
    <p class="text-gray-600">
      确定要删除这条记录吗?此操作不可恢复。
    </p>
    
    <template #footer>
      <Button variant="outline" @click="visible = false">
        取消
      </Button>
      <Button variant="danger" @click="handleConfirm">
        删除
      </Button>
    </template>
  </Modal>
</template>

可访问性要求

<template>
  <div
    role="dialog"
    aria-modal="true"
    :aria-labelledby="titleId"
    :aria-describedby="descId"
  >
    <h2 :id="titleId">{{ title }}</h2>
    <p :id="descId">{{ description }}</p>
    
    <!-- 焦点陷阱:Tab 键在 Modal 内循环 -->
    <FocusTrap>
      <slot />
    </FocusTrap>
  </div>
</template>

Notification 通知组件

设计规范

相比 Toast 更丰富,支持:

  • 标题 + 描述
  • 操作按钮
  • 自定义图标
  • 持久显示

实现示例

<template>
  <div class="notification" :class="`notification-${type}`">
    <div class="notification-icon">
      <component :is="iconMap[type]" />
    </div>
    
    <div class="notification-content">
      <h4 class="notification-title">{{ title }}</h4>
      <p v-if="description" class="notification-desc">
        {{ description }}
      </p>
      
      <div v-if="actions" class="notification-actions">
        <button 
          v-for="action in actions" 
          :key="action.text"
          @click="action.onClick"
        >
          {{ action.text }}
        </button>
      </div>
    </div>
    
    <button class="notification-close" @click="$emit('close')">
      <IconClose />
    </button>
  </div>
</template>

Alert 提示组件

页面内嵌提示

适用于需要持续显示的信息:

<template>
  <div class="alert" :class="`alert-${type}`" role="alert">
    <component :is="iconMap[type]" class="alert-icon" />
    
    <div class="alert-content">
      <slot />
    </div>
    
    <button v-if="closable" @click="$emit('close')" class="alert-close">
      <IconClose />
    </button>
  </div>
</template>

<style scoped>
.alert {
  display: flex;
  align-items: flex-start;
  padding: 1rem;
  border-radius: 0.5rem;
  margin-bottom: 1rem;
}

.alert-info {
  background: #eff6ff;
  border: 1px solid #bfdbfe;
  color: #1e40af;
}

.alert-warning {
  background: #fffbeb;
  border: 1px solid #fde68a;
  color: #92400e;
}

.alert-error {
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #991b1b;
}

.alert-success {
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  color: #166534;
}
</style>

Loading 加载状态

全局加载

<template>
  <Teleport to="body">
    <Transition name="fade">
      <div v-if="loading" class="global-loading">
        <div class="loading-overlay" />
        <div class="loading-content">
          <Spinner />
          <p v-if="message">{{ message }}</p>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

骨架屏

<template>
  <div v-if="loading" class="skeleton">
    <div class="skeleton-avatar" />
    <div class="skeleton-content">
      <div class="skeleton-line w-3/4" />
      <div class="skeleton-line w-1/2" />
    </div>
  </div>
  <div v-else>
    <slot />
  </div>
</template>

<style scoped>
.skeleton-line {
  height: 1rem;
  background: linear-gradient(
    90deg,
    #f0f0f0 25%,
    #e0e0e0 50%,
    #f0f0f0 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 0.25rem;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
</style>

使用场景决策

用户需要知道操作结果?
├── 是否需要确认?
│   ├── 是 → Modal
│   └── 否 → Toast
│
用户需要采取行动?
├── 紧急程度高?
│   ├── 是 → Modal / Notification
│   └── 否 → Alert(内嵌)
│
单纯信息展示?
├── 自动消失 → Toast
└── 持续展示 → Alert / Notification

最佳实践

原则说明
适度使用避免过多干扰用户
位置一致同类提示位置固定
信息清晰简洁明了的文案
可操作性提供明确的后续操作
可访问性支持屏幕阅读器

总结

反馈提示组件设计的核心在于:

  1. 选择合适类型 - 根据场景选择 Toast/Modal/Alert
  2. 把握干扰程度 - 轻提示用 Toast,重决策用 Modal
  3. 保持一致性 - 统一的视觉风格和交互方式
  4. 注重可访问性 - 遵循 ARIA 规范

好的反馈系统让用户始终了解系统状态,提升使用信心。