Button 按钮组件 
按钮用于开始一个即时操作。
学习目标 
- 掌握 Element Plus Button 组件的各种类型和属性
- 了解按钮的基本设计原则和使用场景
- 学习按钮的状态管理和交互效果
- 掌握按钮组合和布局技巧
基础用法 
使用 type、plain、round 和 circle 来定义按钮的样式。
基础按钮
使用 type 属性来定义按钮的类型。
vue
<template>
  <div class="button-demo">
    <el-button>默认按钮</el-button>
    <el-button type="primary">主要按钮</el-button>
    <el-button type="success">成功按钮</el-button>
    <el-button type="info">信息按钮</el-button>
    <el-button type="warning">警告按钮</el-button>
    <el-button type="danger">危险按钮</el-button>
  </div>
</template>
<style scoped>
.button-demo {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
</style>朴素按钮 
朴素按钮同样设置了 type 属性,它们的表现与常规按钮不同,边框和文字颜色都是彩色的。
朴素按钮
vue
<template>
  <div class="plain-button-demo">
    <el-button plain>朴素按钮</el-button>
    <el-button type="primary" plain>主要按钮</el-button>
    <el-button type="success" plain>成功按钮</el-button>
    <el-button type="info" plain>信息按钮</el-button>
    <el-button type="warning" plain>警告按钮</el-button>
    <el-button type="danger" plain>危险按钮</el-button>
  </div>
</template>圆角按钮 
通过 round 属性来确定按钮是否为圆角按钮。
圆角按钮
vue
<template>
  <div class="round-button-demo">
    <el-button round>圆角按钮</el-button>
    <el-button type="primary" round>主要按钮</el-button>
    <el-button type="success" round>成功按钮</el-button>
    <el-button type="info" round>信息按钮</el-button>
    <el-button type="warning" round>警告按钮</el-button>
    <el-button type="danger" round>危险按钮</el-button>
  </div>
</template>图标按钮 
使用图标为按钮添加更多的含义。你也可以单独使用图标不添加文字来节省显示区域占用。
图标按钮
vue
<template>
  <div class="icon-button-demo">
    <!-- 带图标的按钮 -->
    <el-button type="primary" :icon="Edit">编辑</el-button>
    <el-button type="primary" :icon="Share">分享</el-button>
    <el-button type="primary" :icon="Delete">删除</el-button>
    <el-button type="primary" :icon="Search">搜索</el-button>
    
    <!-- 只有图标的按钮 -->
    <el-button type="primary" :icon="Edit" circle />
    <el-button type="success" :icon="Check" circle />
    <el-button type="info" :icon="Message" circle />
    <el-button type="warning" :icon="Star" circle />
    <el-button type="danger" :icon="Delete" circle />
  </div>
</template>
<script setup>
import {
  Edit,
  Share,
  Delete,
  Search,
  Check,
  Message,
  Star
} from '@element-plus/icons-vue'
</script>
<style scoped>
.button-group-demo {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
</style>按钮尺寸 
Button 组件提供除了默认值以外的三种尺寸,可以在不同场景下选择合适的按钮尺寸。
按钮尺寸
vue
<template>
  <div class="size-button-demo">
    <el-row>
      <el-button size="large">大型按钮</el-button>
      <el-button>默认按钮</el-button>
      <el-button size="small">小型按钮</el-button>
    </el-row>
    <el-row>
      <el-button size="large" round>大型按钮</el-button>
      <el-button round>默认按钮</el-button>
      <el-button size="small" round>小型按钮</el-button>
    </el-row>
    <el-row>
      <el-button size="large" :icon="Search" circle />
      <el-button :icon="Search" circle />
      <el-button size="small" :icon="Search" circle />
    </el-row>
  </div>
</template>
<script setup>
import { Search } from '@element-plus/icons-vue'
</script>
<style scoped>
.size-button-demo .el-row {
  margin-bottom: 20px;
}
.size-button-demo .el-row:last-child {
  margin-bottom: 0;
}
</style>禁用状态 
你可以使用 disabled 属性来定义按钮是否被禁用。
禁用状态
vue
<template>
  <div class="disabled-button-demo">
    <el-row>
      <el-button disabled>默认按钮</el-button>
      <el-button type="primary" disabled>主要按钮</el-button>
      <el-button type="success" disabled>成功按钮</el-button>
      <el-button type="info" disabled>信息按钮</el-button>
      <el-button type="warning" disabled>警告按钮</el-button>
      <el-button type="danger" disabled>危险按钮</el-button>
    </el-row>
    
    <el-row>
      <el-button plain disabled>朴素按钮</el-button>
      <el-button type="primary" plain disabled>主要按钮</el-button>
      <el-button type="success" plain disabled>成功按钮</el-button>
      <el-button type="info" plain disabled>信息按钮</el-button>
      <el-button type="warning" plain disabled>警告按钮</el-button>
      <el-button type="danger" plain disabled>危险按钮</el-button>
    </el-row>
  </div>
</template>链接按钮 
链接按钮用于创建类似链接的按钮样式。
链接按钮
vue
<template>
  <div class="link-button-demo">
    <el-button type="primary" link>基础链接按钮</el-button>
    <el-button type="primary" link disabled>禁用链接按钮</el-button>
  </div>
</template>文字按钮 
没有边框和背景色的按钮。
文字按钮
vue
<template>
  <div class="text-button-demo">
    <el-button type="primary" text>文字按钮</el-button>
    <el-button type="primary" text bg>背景文字按钮</el-button>
    <el-button type="primary" text disabled>禁用文字按钮</el-button>
  </div>
</template>加载状态 
点击按钮来加载数据,并向用户反馈加载状态。
加载状态
vue
<template>
  <div class="loading-button-demo">
    <el-button type="primary" loading>加载中</el-button>
    <el-button type="primary" :loading="loading" @click="handleClick">
      点击加载
    </el-button>
  </div>
</template>
<script setup>
import { ref } from 'vue'
const loading = ref(false)
const handleClick = () => {
  loading.value = true
  setTimeout(() => {
    loading.value = false
  }, 2000)
}
</script>自定义颜色 
您可以自定义按钮的颜色,我们将自动计算按钮处于 hover 和 active 状态时的颜色。
自定义颜色
vue
<template>
  <div class="custom-color-demo">
    <el-button color="#95d475">#95d475</el-button>
    <el-button color="#95d475" plain>#95d475</el-button>
    <el-button color="#95d475" round plain>圆角按钮</el-button>
    <el-button color="#95d475" round>圆角按钮</el-button>
  </div>
</template>自定义元素标签 
您可以自定义元素标签,例如按钮、div、路由链接、nuxt链接。
自定义元素标签
vue
<template>
  <div class="custom-tag-demo">
    <el-button tag="div" role="button" tabindex="0">div</el-button>
    <el-button tag="span" role="button" tabindex="0">span</el-button>
  </div>
</template>自动插入空格 
当按钮内容为两个中文字符时,可以自动在字符之间插入空格。
自动插入空格
vue
<template>
  <div class="auto-space-demo">
    <el-button auto-insert-space>按钮</el-button>
    <el-button :auto-insert-space="false">按钮</el-button>
  </div>
</template>按钮组 
以按钮组的方式出现,常用于多项类似操作。
按钮组
vue
<template>
  <div class="button-group-demo">
    <el-button-group>
      <el-button type="primary" :icon="ArrowLeft">上一页</el-button>
      <el-button type="primary" :icon="ArrowRight">下一页</el-button>
    </el-button-group>
    <br><br>
    <el-button-group>
      <el-button type="primary" :icon="Edit" />
      <el-button type="primary" :icon="Share" />
      <el-button type="primary" :icon="Delete" />
    </el-button-group>
  </div>
</template>
<script setup>
import {
  ArrowLeft,
  ArrowRight,
  Edit,
  Share,
  Delete
} from '@element-plus/icons-vue'
</script>
<style scoped>
.button-group-demo {
  display: flex;
  gap: 20px;
}
</style>综合示例 
按钮工具栏 
按钮工具栏
状态指示器 
状态指示器
运行中
警告
错误
停止
Button API 
Button Attributes 
| 属性名 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| size | 尺寸 | string | large / default / small | — | 
| type | 类型 | string | primary / success / warning / danger / info | — | 
| plain | 是否朴素按钮 | boolean | — | false | 
| text ^(2.2.0) | 是否文字按钮 | boolean | — | false | 
| bg ^(2.2.0) | 是否显示文字按钮背景颜色 | boolean | — | false | 
| link ^(2.2.1) | 是否链接按钮 | boolean | — | false | 
| round | 是否圆角按钮 | boolean | — | false | 
| circle | 是否圆形按钮 | boolean | — | false | 
| loading | 是否加载中状态 | boolean | — | false | 
| loading-icon | 自定义加载中状态图标组件 | string / Component | — | Loading | 
| disabled | 是否禁用状态 | boolean | — | false | 
| icon | 图标组件 | string / Component | — | — | 
| autofocus | 是否默认聚焦 | boolean | — | false | 
| native-type | 原生 type 属性 | string | button / submit / reset | button | 
| auto-insert-space | 自动在两个中文字符之间插入空格 | boolean | — | false | 
| color | 自定义按钮颜色, 并自动计算 hover 和 active 触发后的颜色 | string | — | — | 
| dark | dark 模式, 意味着自动设置 color 为 dark 模式的颜色 | boolean | — | false | 
| tag ^(2.3.4) | 自定义元素标签 | string / Component | — | button | 
Button Events 
| 事件名 | 说明 | 回调参数 | 
|---|---|---|
| click | 点击时触发 | (evt: MouseEvent) | 
Button Slots 
| 插槽名 | 说明 | 
|---|---|
| default | 自定义默认内容 | 
| loading | 自定义加载中组件 | 
| icon | 自定义图标组件 | 
Button Exposes 
| 方法名 | 说明 | 类型 | 
|---|---|---|
| ref | 按钮 html 元素 | Ref<HTMLButtonElement> | 
| size | 按钮尺寸 | ComputedRef<string> | 
| type | 按钮类型 | ComputedRef<string> | 
| disabled | 按钮是否禁用 | ComputedRef<boolean> | 
| shouldAddSpace | 是否在两个字符之间添加空格 | ComputedRef<boolean> | 
Button Exposes 使用示例 
通过模板引用可以访问按钮组件暴露的属性和方法:
vue
<template>
  <div class="button-exposes-demo">
    <h3>Button Exposes 示例</h3>
    
    <!-- 按钮组件 -->
    <div class="button-section">
      <el-button 
        ref="primaryButtonRef"
        type="primary" 
        :size="buttonSize"
        :disabled="isDisabled"
        @click="handleButtonClick"
      >
        主要按钮
      </el-button>
      
      <el-button 
        ref="successButtonRef"
        type="success" 
        size="large"
        auto-insert-space
      >
        成功按钮
      </el-button>
    </div>
    
    <!-- 控制面板 -->
    <div class="control-panel">
      <h4>控制面板</h4>
      <div class="control-item">
        <label>按钮尺寸:</label>
        <el-select v-model="buttonSize" style="width: 120px">
          <el-option label="Large" value="large" />
          <el-option label="Default" value="default" />
          <el-option label="Small" value="small" />
        </el-select>
      </div>
      
      <div class="control-item">
        <el-checkbox v-model="isDisabled">禁用按钮</el-checkbox>
      </div>
      
      <div class="control-item">
        <el-button @click="getButtonInfo">获取按钮信息</el-button>
        <el-button @click="focusButton">聚焦按钮</el-button>
      </div>
    </div>
    
    <!-- 信息显示 -->
    <div class="info-panel">
      <h4>按钮信息</h4>
      <div class="info-item">
        <strong>主要按钮尺寸:</strong> {{ primaryButtonInfo.size }}
      </div>
      <div class="info-item">
        <strong>主要按钮类型:</strong> {{ primaryButtonInfo.type }}
      </div>
      <div class="info-item">
        <strong>主要按钮禁用状态:</strong> {{ primaryButtonInfo.disabled }}
      </div>
      <div class="info-item">
        <strong>成功按钮是否添加空格:</strong> {{ successButtonInfo.shouldAddSpace }}
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, nextTick } from 'vue'
// 模板引用
const primaryButtonRef = ref()
const successButtonRef = ref()
// 响应式数据
const buttonSize = ref('default')
const isDisabled = ref(false)
// 按钮信息
const primaryButtonInfo = reactive({
  size: '',
  type: '',
  disabled: false
})
const successButtonInfo = reactive({
  shouldAddSpace: false
})
// 获取按钮信息
const getButtonInfo = () => {
  if (primaryButtonRef.value) {
    primaryButtonInfo.size = primaryButtonRef.value.size
    primaryButtonInfo.type = primaryButtonRef.value.type
    primaryButtonInfo.disabled = primaryButtonRef.value.disabled
  }
  
  if (successButtonRef.value) {
    successButtonInfo.shouldAddSpace = successButtonRef.value.shouldAddSpace
  }
}
// 聚焦按钮
const focusButton = async () => {
  await nextTick()
  if (primaryButtonRef.value?.ref) {
    primaryButtonRef.value.ref.focus()
  }
}
// 按钮点击事件
const handleButtonClick = () => {
  console.log('按钮被点击了')
  getButtonInfo() // 点击时自动更新信息
}
// 初始化信息
nextTick(() => {
  getButtonInfo()
})
</script>
<style scoped>
.button-exposes-demo {
  padding: 20px;
}
.button-section {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-bg-color);
}
.button-section .el-button {
  margin-right: 10px;
}
.control-panel {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-fill-color-lighter);
}
.control-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}
.control-item label {
  width: 80px;
  margin-right: 10px;
  font-weight: 500;
}
.control-item .el-button {
  margin-right: 10px;
}
.info-panel {
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-fill-color-extra-light);
}
.info-item {
  margin-bottom: 8px;
  color: var(--el-text-color-primary);
}
.info-item strong {
  color: var(--el-color-primary);
}
</style>高级用法:动态按钮管理 
vue
<template>
  <div class="advanced-button-demo">
    <h3>动态按钮管理</h3>
    
    <!-- 动态按钮列表 -->
    <div class="button-list">
      <el-button
        v-for="(button, index) in buttons"
        :key="button.id"
        :ref="el => setButtonRef(el, index)"
        :type="button.type"
        :size="button.size"
        :disabled="button.disabled"
        :loading="button.loading"
        @click="handleDynamicButtonClick(button, index)"
      >
        {{ button.text }}
      </el-button>
    </div>
    
    <!-- 操作控制 -->
    <div class="operations">
      <el-button @click="addButton">添加按钮</el-button>
      <el-button @click="removeLastButton">移除最后一个</el-button>
      <el-button @click="toggleAllButtons">切换全部状态</el-button>
      <el-button @click="getAllButtonsInfo">获取所有按钮信息</el-button>
    </div>
    
    <!-- 按钮信息展示 -->
    <div class="buttons-info" v-if="buttonsInfo.length > 0">
      <h4>按钮信息列表</h4>
      <div 
        v-for="(info, index) in buttonsInfo" 
        :key="index"
        class="button-info-item"
      >
        <strong>按钮 {{ index + 1 }}:</strong>
        类型: {{ info.type }}, 
        尺寸: {{ info.size }}, 
        禁用: {{ info.disabled }}
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, nextTick } from 'vue'
// 按钮数据
const buttons = ref([
  { id: 1, text: '按钮 1', type: 'primary', size: 'default', disabled: false, loading: false },
  { id: 2, text: '按钮 2', type: 'success', size: 'default', disabled: false, loading: false },
  { id: 3, text: '按钮 3', type: 'warning', size: 'default', disabled: false, loading: false }
])
// 按钮引用数组
const buttonRefs = ref([])
// 按钮信息
const buttonsInfo = ref([])
// 设置按钮引用
const setButtonRef = (el, index) => {
  if (el) {
    buttonRefs.value[index] = el
  }
}
// 添加按钮
const addButton = () => {
  const newId = Math.max(...buttons.value.map(b => b.id)) + 1
  const types = ['primary', 'success', 'warning', 'danger', 'info']
  const randomType = types[Math.floor(Math.random() * types.length)]
  
  buttons.value.push({
    id: newId,
    text: `按钮 ${newId}`,
    type: randomType,
    size: 'default',
    disabled: false,
    loading: false
  })
}
// 移除最后一个按钮
const removeLastButton = () => {
  if (buttons.value.length > 1) {
    buttons.value.pop()
    buttonRefs.value.pop()
  }
}
// 切换所有按钮状态
const toggleAllButtons = () => {
  buttons.value.forEach(button => {
    button.disabled = !button.disabled
  })
}
// 动态按钮点击事件
const handleDynamicButtonClick = async (button, index) => {
  // 设置加载状态
  button.loading = true
  
  // 模拟异步操作
  setTimeout(() => {
    button.loading = false
    console.log(`点击了按钮: ${button.text}`)
  }, 1000)
  
  // 获取当前按钮信息
  await nextTick()
  if (buttonRefs.value[index]) {
    const buttonRef = buttonRefs.value[index]
    console.log('按钮信息:', {
      type: buttonRef.type,
      size: buttonRef.size,
      disabled: buttonRef.disabled
    })
  }
}
// 获取所有按钮信息
const getAllButtonsInfo = async () => {
  await nextTick()
  buttonsInfo.value = buttonRefs.value.map(buttonRef => {
    if (buttonRef) {
      return {
        type: buttonRef.type,
        size: buttonRef.size,
        disabled: buttonRef.disabled
      }
    }
    return null
  }).filter(Boolean)
}
</script>
<style scoped>
.advanced-button-demo {
  padding: 20px;
}
.button-list {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-bg-color);
}
.button-list .el-button {
  margin: 0 10px 10px 0;
}
.operations {
  margin-bottom: 20px;
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-fill-color-lighter);
}
.operations .el-button {
  margin-right: 10px;
}
.buttons-info {
  padding: 15px;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  background-color: var(--el-fill-color-extra-light);
}
.button-info-item {
  margin-bottom: 8px;
  padding: 8px;
  background-color: var(--el-bg-color);
  border-radius: var(--el-border-radius-small);
  color: var(--el-text-color-primary);
}
.button-info-item strong {
  color: var(--el-color-primary);
}
</style>ButtonGroup Attributes 
| 属性名 | 说明 | 类型 | 可选值 | 默认值 | 
|---|---|---|---|---|
| size | 用于控制该按钮组内按钮的大小 | string | large / default / small | — | 
| type | 用于控制该按钮组内按钮的类型 | string | primary / success / warning / danger / info | — | 
ButtonGroup Slots 
| 插槽名 | 说明 | 子标签 | 
|---|---|---|
| default | 自定义按钮组内容 | Button | 
实践练习 
练习 1:创建按钮组合 
创建一个包含不同类型、尺寸和状态的按钮组合:
- 实现一个工具栏,包含主要操作按钮
- 添加按钮的加载状态和禁用状态
- 使用按钮组创建分页控件
- 实现响应式按钮布局
练习 2:按钮交互效果 
练习按钮的交互和状态管理:
- 实现按钮的点击反馈效果
- 创建动态加载状态的按钮
- 实现按钮的条件禁用
- 添加按钮的确认对话框
练习 3:自定义按钮样式 
基于 Element Plus 按钮创建自定义样式:
- 定义自己的按钮主题色彩
- 创建特殊形状的按钮
- 实现按钮的动画效果
- 适配移动端的按钮样式
学习资源 
作业 
- 完成所有实践练习
- 创建一个完整的按钮展示页面,包含所有类型和状态
- 实现一个带有确认功能的删除按钮组件
- 研究其他 UI 框架的按钮设计,对比分析优缺点
下一步学习计划 
接下来我们将学习 表单组件,包括:
- Input 输入框组件
- Select 选择器组件
- Checkbox 复选框组件
- Radio 单选框组件