Skip to content

Alert 提示

学习目标

通过本章学习,你将掌握:

  • 基础警告组件的使用方法
  • 警告类型主题和样式设置
  • 可关闭警告和图标设置
  • 警告标题描述和操作区域
  • 警告动画效果和最佳实践

预计学习时间: 75分钟

概述

Alert 提示是一个用于页面中展示重要提示信息的静态组件。它不属于浮层元素,不会自动消失或关闭,适合展示需要用户明确知晓的重要信息。

主要特性

  • 多种类型:支持成功、信息、警告、错误、主要等5种提示类型
  • 主题样式:提供明亮和暗色两种主题效果
  • 可关闭性:支持用户手动关闭,可自定义关闭按钮文本
  • 图标支持:内置类型图标,也支持自定义图标内容
  • 内容丰富:支持标题、描述文本,满足不同信息展示需求
  • 布局灵活:支持文字居中对齐,适应不同设计需求
  • 延迟控制:支持延迟显示和自动关闭功能

适用场景

  • 系统通知:如系统维护通知、版本更新说明等
  • 操作反馈:如表单提交成功、操作失败提示等
  • 状态提示:如页面加载状态、功能限制说明等
  • 警告信息:如安全提醒、重要注意事项等
  • 帮助说明:如功能介绍、使用指南等

基础用法

基础用法

Alert 组件提供5种类型,由 type 属性指定,默认值为 info

vue
<template>
  <el-alert title="success alert" type="success" />
  <el-alert title="info alert" type="info" />
  <el-alert title="warning alert" type="warning" />
  <el-alert title="error alert" type="error" />
  <el-alert title="primary alert" type="primary" />
</template>

<style scoped>
.el-alert {
  margin: 20px 0 0;
}
.el-alert:first-child {
  margin: 0;
}
</style>

主题

Alert 组件提供了两个不同的主题:lightdark。通过设置 effect 属性来改变主题,默认为 light

vue
<template>
  <el-alert title="success alert" type="success" effect="dark" />
  <el-alert title="info alert" type="info" effect="dark" />
  <el-alert title="warning alert" type="warning" effect="dark" />
  <el-alert title="error alert" type="error" effect="dark" />
</template>

自定义关闭按钮

你可以自定义关闭按钮为文字或其他符号。closable 属性决定 Alert 组件是否可关闭,该属性接受一个 Boolean,默认为 true。你可以设置 close-text 属性来代替右侧的关闭图标。当 Alert 组件被关闭时会触发 close 事件。

vue
<template>
  <el-alert title="unclosable alert" type="success" :closable="false" />
  <el-alert title="customized close-text" type="info" close-text="Gotcha" />
  <el-alert title="alert with callback" type="warning" @close="hello" />
</template>

<script lang="ts" setup>
const hello = () => {
  alert('Hello World!')
}
</script>

使用图标

通过设置 show-icon 属性来显示 Alert 的 icon,这能更有效地向用户展示你的显示意图。或者你可以使用 icon slot 自定义 icon 内容。

vue
<template>
  <el-alert title="success alert" type="success" show-icon />
  <el-alert title="info alert" type="info" show-icon />
  <el-alert title="warning alert" type="warning" show-icon />
  <el-alert title="error alert" type="error" show-icon />
</template>

文字居中

使用 center 属性来让文字水平居中。

vue
<template>
  <el-alert title="success alert" type="success" center show-icon />
  <el-alert title="info alert" type="info" center show-icon />
  <el-alert title="warning alert" type="warning" center show-icon />
  <el-alert title="error alert" type="error" center show-icon />
</template>

文字描述

除了必填的 title 属性外,你可以设置 description 属性来帮助你更好地介绍,我们称之为辅助性文字。辅助性文字只能存放文本内容,当内容超出长度限制时会自动换行显示。

vue
<template>
  <el-alert
    title="with description"
    type="success"
    description="This is a description."
  />
</template>

带图标和描述

这是一个带有图标和描述的例子。

vue
<template>
  <el-alert
    title="success alert"
    type="success"
    description="more text description"
    show-icon
  />
  <el-alert
    title="info alert"
    type="info"
    description="more text description"
    show-icon
  />
  <el-alert
    title="warning alert"
    type="warning"
    description="more text description"
    show-icon
  />
  <el-alert
    title="error alert"
    type="error"
    description="more text description"
    show-icon
  />
</template>

延迟属性

可以设置延迟显示和自动关闭的功能。

vue
<template>
  <el-alert
    title="延迟显示"
    type="info"
    :show-after="1000"
  />
  <el-alert
    title="自动关闭"
    type="warning"
    :auto-close="3000"
  />
</template>

实际应用示例

系统状态面板

一个完整的系统状态展示面板,包含不同类型的提示信息。

vue
<template>
  <div class="system-status-panel">
    <h2>系统状态监控</h2>
    
    <!-- 系统维护通知 -->
    <el-alert
      v-if="maintenanceInfo.show"
      :title="maintenanceInfo.title"
      type="warning"
      :description="maintenanceInfo.description"
      show-icon
      :closable="false"
      effect="dark"
      class="maintenance-alert"
    />
    
    <!-- 服务状态列表 -->
    <div class="service-status">
      <h3>服务状态</h3>
      <div class="status-grid">
        <el-alert
          v-for="service in services"
          :key="service.name"
          :title="service.name"
          :type="service.status"
          :description="service.description"
          show-icon
          :closable="false"
          class="service-item"
        >
          <template #title>
            <div class="service-title">
              <span>{{ service.name }}</span>
              <el-tag :type="service.status" size="small">{{ service.statusText }}</el-tag>
            </div>
          </template>
        </el-alert>
      </div>
    </div>
    
    <!-- 操作结果提示 -->
    <div class="operation-feedback">
      <h3>操作反馈</h3>
      <el-alert
        v-for="feedback in operationFeedbacks"
        :key="feedback.id"
        :title="feedback.title"
        :type="feedback.type"
        :description="feedback.description"
        show-icon
        :auto-close="feedback.autoClose"
        @close="removeFeedback(feedback.id)"
        class="feedback-item"
      />
    </div>
    
    <!-- 帮助信息 -->
    <el-alert
      title="使用提示"
      type="info"
      :closable="false"
      class="help-info"
    >
      <template #default>
        <ul class="help-list">
          <li>绿色表示服务正常运行</li>
          <li>黄色表示服务有警告或需要注意</li>
          <li>红色表示服务异常或不可用</li>
          <li>点击刷新按钮可以更新服务状态</li>
        </ul>
      </template>
    </el-alert>
    
    <!-- 操作按钮 -->
    <div class="actions">
      <el-button type="primary" @click="refreshStatus">刷新状态</el-button>
      <el-button @click="addTestFeedback">测试反馈</el-button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive } from 'vue'

interface Service {
  name: string
  status: 'success' | 'warning' | 'error'
  statusText: string
  description: string
}

interface Feedback {
  id: number
  title: string
  type: 'success' | 'warning' | 'error' | 'info'
  description: string
  autoClose?: number
}

const maintenanceInfo = reactive({
  show: true,
  title: '系统维护通知',
  description: '系统将于今晚 23:00-01:00 进行例行维护,期间部分功能可能受到影响。'
})

const services = ref<Service[]>([
  {
    name: '用户服务',
    status: 'success',
    statusText: '正常',
    description: '响应时间: 45ms | 可用性: 99.9%'
  },
  {
    name: '支付服务',
    status: 'warning',
    statusText: '警告',
    description: '响应时间: 120ms | 可用性: 98.5% | 负载较高'
  },
  {
    name: '邮件服务',
    status: 'error',
    statusText: '异常',
    description: '服务不可用 | 正在修复中'
  },
  {
    name: '文件存储',
    status: 'success',
    statusText: '正常',
    description: '响应时间: 32ms | 可用性: 99.8%'
  }
])

let feedbackId = 1
const operationFeedbacks = ref<Feedback[]>([
  {
    id: feedbackId++,
    title: '数据同步完成',
    type: 'success',
    description: '用户数据已成功同步到备份服务器',
    autoClose: 5000
  }
])

const refreshStatus = () => {
  // 模拟刷新状态
  const randomStatus = () => {
    const statuses: Array<'success' | 'warning' | 'error'> = ['success', 'warning', 'error']
    return statuses[Math.floor(Math.random() * statuses.length)]
  }
  
  services.value.forEach(service => {
    const newStatus = randomStatus()
    service.status = newStatus
    service.statusText = newStatus === 'success' ? '正常' : newStatus === 'warning' ? '警告' : '异常'
  })
  
  // 添加刷新成功反馈
  operationFeedbacks.value.push({
    id: feedbackId++,
    title: '状态刷新成功',
    type: 'success',
    description: '系统状态已更新',
    autoClose: 3000
  })
}

const addTestFeedback = () => {
  const feedbacks = [
    { title: '配置更新', type: 'info' as const, description: '系统配置已更新' },
    { title: '备份完成', type: 'success' as const, description: '数据备份已完成' },
    { title: '磁盘空间不足', type: 'warning' as const, description: '服务器磁盘使用率超过 80%' },
    { title: '连接失败', type: 'error' as const, description: '无法连接到外部API服务' }
  ]
  
  const randomFeedback = feedbacks[Math.floor(Math.random() * feedbacks.length)]
  operationFeedbacks.value.push({
    id: feedbackId++,
    ...randomFeedback,
    autoClose: 4000
  })
}

const removeFeedback = (id: number) => {
  const index = operationFeedbacks.value.findIndex(f => f.id === id)
  if (index > -1) {
    operationFeedbacks.value.splice(index, 1)
  }
}
</script>

<style scoped>
.system-status-panel {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

.system-status-panel h2 {
  color: #333;
  margin-bottom: 20px;
  text-align: center;
}

.system-status-panel h3 {
  color: #666;
  margin: 25px 0 15px;
  font-size: 16px;
}

.maintenance-alert {
  margin-bottom: 25px;
}

.status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 15px;
  margin-bottom: 25px;
}

.service-item {
  border-radius: 8px;
}

.service-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.operation-feedback {
  margin: 25px 0;
}

.feedback-item {
  margin-bottom: 10px;
}

.help-info {
  margin: 25px 0;
}

.help-list {
  margin: 0;
  padding-left: 20px;
  color: #666;
}

.help-list li {
  margin: 5px 0;
  line-height: 1.5;
}

.actions {
  text-align: center;
  margin-top: 30px;
}

.actions .el-button {
  margin: 0 10px;
}
</style>

表单验证提示

在表单中使用 Alert 组件展示验证结果和提示信息。

vue
<template>
  <div class="form-validation-demo">
    <h2>用户注册</h2>
    
    <!-- 表单说明 -->
    <el-alert
      title="注册须知"
      type="info"
      :closable="false"
      class="form-notice"
    >
      <template #default>
        <p>请填写真实信息完成注册,标有 <span class="required">*</span> 的为必填项</p>
      </template>
    </el-alert>
    
    <!-- 验证结果提示 -->
    <transition name="fade">
      <el-alert
        v-if="validationResult.show"
        :title="validationResult.title"
        :type="validationResult.type"
        :description="validationResult.description"
        show-icon
        @close="validationResult.show = false"
        class="validation-result"
      />
    </transition>
    
    <!-- 注册表单 -->
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="100px"
      class="registration-form"
    >
      <el-form-item label="用户名" prop="username">
        <el-input v-model="form.username" placeholder="请输入用户名" />
      </el-form-item>
      
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form.email" type="email" placeholder="请输入邮箱地址" />
      </el-form-item>
      
      <el-form-item label="密码" prop="password">
        <el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
      </el-form-item>
      
      <el-form-item label="确认密码" prop="confirmPassword">
        <el-input v-model="form.confirmPassword" type="password" placeholder="请再次输入密码" show-password />
      </el-form-item>
      
      <!-- 密码强度提示 -->
      <el-alert
        v-if="passwordStrength.show"
        :title="passwordStrength.title"
        :type="passwordStrength.type"
        :description="passwordStrength.description"
        show-icon
        :closable="false"
        class="password-strength"
      />
      
      <el-form-item>
        <el-button type="primary" @click="submitForm" :loading="submitting">
          注册
        </el-button>
        <el-button @click="resetForm">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

const formRef = ref<FormInstance>()
const submitting = ref(false)

const form = reactive({
  username: '',
  email: '',
  password: '',
  confirmPassword: ''
})

const validationResult = reactive({
  show: false,
  title: '',
  type: 'success' as 'success' | 'warning' | 'error' | 'info',
  description: ''
})

// 密码强度检测
const passwordStrength = computed(() => {
  if (!form.password) {
    return { show: false, title: '', type: 'info', description: '' }
  }
  
  const password = form.password
  let strength = 0
  let tips = []
  
  if (password.length >= 8) strength++
  else tips.push('至少8个字符')
  
  if (/[a-z]/.test(password)) strength++
  else tips.push('包含小写字母')
  
  if (/[A-Z]/.test(password)) strength++
  else tips.push('包含大写字母')
  
  if (/\d/.test(password)) strength++
  else tips.push('包含数字')
  
  if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) strength++
  else tips.push('包含特殊字符')
  
  if (strength >= 4) {
    return {
      show: true,
      title: '密码强度:强',
      type: 'success' as const,
      description: '密码强度良好'
    }
  } else if (strength >= 2) {
    return {
      show: true,
      title: '密码强度:中等',
      type: 'warning' as const,
      description: `建议:${tips.slice(0, 2).join('、')}`
    }
  } else {
    return {
      show: true,
      title: '密码强度:弱',
      type: 'error' as const,
      description: `需要:${tips.slice(0, 3).join('、')}`
    }
  }
})

const validateConfirmPassword = (rule: any, value: string, callback: Function) => {
  if (value !== form.password) {
    callback(new Error('两次输入的密码不一致'))
  } else {
    callback()
  }
}

const rules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 20, message: '用户名长度在 3 到 20 个字符', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '请输入邮箱地址', trigger: 'blur' },
    { type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, message: '密码长度不能少于 6 个字符', trigger: 'blur' }
  ],
  confirmPassword: [
    { required: true, message: '请再次输入密码', trigger: 'blur' },
    { validator: validateConfirmPassword, trigger: 'blur' }
  ]
}

const submitForm = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    submitting.value = true
    
    // 模拟提交
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    validationResult.show = true
    validationResult.title = '注册成功'
    validationResult.type = 'success'
    validationResult.description = '恭喜您,账户注册成功!请查收邮箱验证邮件。'
    
  } catch (error) {
    validationResult.show = true
    validationResult.title = '注册失败'
    validationResult.type = 'error'
    validationResult.description = '请检查表单信息并重试'
  } finally {
    submitting.value = false
  }
}

const resetForm = () => {
  if (!formRef.value) return
  formRef.value.resetFields()
  validationResult.show = false
}
</script>

<style scoped>
.form-validation-demo {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.form-validation-demo h2 {
  text-align: center;
  color: #333;
  margin-bottom: 20px;
}

.form-notice {
  margin-bottom: 20px;
}

.required {
  color: #f56c6c;
  font-weight: bold;
}

.validation-result {
  margin-bottom: 20px;
}

.registration-form {
  margin-top: 20px;
}

.password-strength {
  margin-bottom: 15px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>

API

Attributes

属性名说明类型可选值默认值
titleAlert 标题string
typeAlert 类型stringsuccess/warning/info/error/primaryinfo
description描述性文本string
closable是否可以关闭booleantrue
center文字是否居中booleanfalse
close-text自定义关闭按钮文本string
show-icon是否显示类型图标booleanfalse
effect主题样式stringlight/darklight
show-after在触发后多久显示内容,单位毫秒number0
hide-after延迟关闭,单位毫秒number200
auto-closealert 出现后自动隐藏延时,单位毫秒number0

Events

事件名说明类型
open开启 Alert 时触发的事件Function
close关闭 Alert 时触发的事件Function

Slots

插槽名说明
defaultAlert 内容描述
title标题的内容
iconicon 的内容

最佳实践

  1. 合理选择类型:根据信息的重要性和性质选择合适的 type

    • success:操作成功的反馈
    • info:一般信息提示
    • warning:需要用户注意的警告信息
    • error:错误信息或操作失败的反馈
    • primary:重要的主要信息
  2. 简洁明了:标题和描述应该简洁明了,避免冗长的文本

  3. 图标使用:在需要快速识别信息类型时使用 show-icon

  4. 主题选择:根据页面整体风格选择合适的主题(light/dark)

  5. 关闭功能:对于重要信息,可以设置 closablefalse 确保用户看到

  6. 延迟显示:对于需要延迟显示的场景,合理使用 show-after 属性

常见问题

1. Alert 组件不会自动消失?

Alert 组件设计为静态提示,不会自动消失。如果需要自动消失的提示,请使用 Message 组件。如果确实需要自动关闭,可以使用 auto-close 属性。

2. 如何自定义图标?

可以使用 icon 插槽来自定义图标内容:

vue
<el-alert title="自定义图标" type="info">
  <template #icon>
    <el-icon><Star /></el-icon>
  </template>
</el-alert>

3. 描述文本过长怎么办?

描述文本会自动换行显示,但建议保持简洁。如果内容较多,考虑使用 Dialog 组件。

4. 如何实现延迟显示和自动关闭?

vue
<el-alert
  title="延迟显示并自动关闭"
  type="success"
  :show-after="1000"
  :auto-close="5000"
/>

Q: 如何实现 Alert 的动画效果?

A: 可以结合 Vue 的 transition 组件来实现自定义的动画效果。

实践项目

反馈系统集成

创建一个完整的页面反馈系统,包含以下功能:

  1. 警告信息展示

    • 系统维护通知
    • 功能限制提醒
    • 安全警告信息
  2. 状态提示面板

    • 操作结果展示
    • 表单验证提示
    • 页面状态说明
  3. 信息公告板

    • 重要公告展示
    • 版本更新说明
    • 使用帮助提示

实践要点

  • 根据信息重要性选择合适的 Alert 类型
  • 设计统一的信息展示规范
  • 实现 Alert 的动态显示和隐藏
  • 优化信息的可读性和用户体验

学习检查清单

  • [ ] 掌握基础警告组件的使用
  • [ ] 理解不同警告类型的应用场景
  • [ ] 熟练配置警告的主题和样式
  • [ ] 掌握可关闭警告和图标设置
  • [ ] 理解警告标题描述和操作区域
  • [ ] 完成反馈系统的实践项目

注意事项

  1. 消息的优先级管理

    • 错误和警告信息优先级最高
    • 成功信息可以适当弱化显示
    • 避免同时显示过多 Alert
  2. 用户注意力的引导

    • 重要信息使用醒目的颜色和图标
    • 关键操作前要有明确的警告
    • 避免信息过载影响用户体验
  3. 反馈信息的及时性

    • 页面状态变化要及时反映
    • 操作限制要提前告知用户
    • 错误信息要准确描述问题
  4. 无障碍访问支持

    • 确保 Alert 内容语义化
    • 提供合适的颜色对比度
    • 考虑屏幕阅读器的兼容性

学习日期: ___________
完成状态: ___________
学习笔记:

遇到的问题:

解决方案:

总结

Alert 提示是一个功能完善的静态反馈组件,具有以下特点:

  • 类型丰富:支持成功、信息、警告、错误、主要等5种提示类型
  • 样式灵活:提供明亮和暗色两种主题,支持文字居中对齐
  • 内容完整:支持标题、描述文本和自定义图标,满足不同信息展示需求
  • 交互友好:支持用户关闭操作,可自定义关闭按钮文本
  • 功能扩展:支持延迟显示和自动关闭,适应复杂业务场景
  • 易于集成:提供丰富的插槽和事件,便于自定义和业务集成

适用于系统通知、操作反馈、状态提示、警告信息等场景。通过合理的类型选择和内容设计,可以有效提升用户对重要信息的感知和理解。

参考资料

Element Plus Study Guide