Skip to content
第 23 章 前端 ⏱ 13 分钟阅读

第 23 章:Element Plus 实战 ​

学习目标 ​

  • 用 el-table 加分页和搜索
  • 用 el-form 写表单
  • 自定义 el-table 列渲染
  • 避坑:表格性能和 slot 类型

一、table + 分页 ​

vue
<template>
  <el-input v-model="keyword" placeholder="搜索" clearable />
  <el-button type="primary" @click="load">查询</el-button>

  <el-table :data="list" v-loading="loading" border>
    <el-table-column prop="id" label="ID" width="80" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column label="操作" width="200">
      <template #default="{ row }">
        <el-button size="small" @click="edit(row)">编辑</el-button>
        <el-button size="small" type="danger" @click="remove(row.id)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>

  <el-pagination
    v-model:current-page="page"
    v-model:page-size="pageSize"
    :total="total"
    layout="total, sizes, prev, pager, next, jumper"
    @current-change="load"
  />
</template>
ts
const keyword = ref('')
const list = ref<User[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const loading = ref(false)

const load = async () => {
  loading.value = true
  const res = await userApi.list({ keyword: keyword.value, page: page.value, pageSize: pageSize.value })
  list.value = res.items
  total.value = res.total
  loading.value = false
}

⚠️ 坑 1:大数据表格要 virtual-list,设置 el-table-v2,否则 1 万行卡死。

二、自定义列渲染 ​

vue
<el-table-column label="状态">
  <template #default="{ row }">
    <el-tag :type="row.status === 1 ? 'success' : 'danger'">
      {{ row.status === 1 ? '启用' : '禁用' }}
    </el-tag>
  </template>
</el-table-column>
vue
<el-table-column label="头像">
  <template #default="{ row }">
    <el-avatar :src="row.avatar" />
  </template>
</el-table-column>

三、Dialog + Form ​

vue
<template>
  <el-dialog v-model="visible" title="编辑用户" width="500px">
    <el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
      <el-form-item label="姓名" prop="name">
        <el-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-switch v-model="form.status" />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="submit">保存</el-button>
    </template>
  </el-dialog>
</template>

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

const formRef = ref<FormInstance>()
const form = reactive({ name: '', status: true })
const rules: FormRules = {
  name: [{ required: true, message: '必填' }],
}

const submit = async () => {
  await formRef.value?.validate()
  await userApi.save(form)
  visible.value = false
  load()
}
</script>

四、菜单 + 面包屑 ​

vue
<el-menu :default-active="route.path" router>
  <el-menu-item index="/home">首页</el-menu-item>
  <el-menu-item index="/users">用户</el-menu-item>
</el-menu>
vue
<el-breadcrumb>
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item>{{ route.meta.title }}</el-breadcrumb-item>
</el-breadcrumb>

五、消息 & 通知 ​

ts
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'

ElMessage.success('保存成功')
ElMessageBox.confirm('确定删除?', '提示', { type: 'warning' })
  .then(() => ElMessage.success('已删除'))
ElNotification({ title: '通知', message: '新订单', type: 'success' })

⚠️ 坑 2:ElMessageBox 链式 .then 之前的链上必须 catch,否则 unhandled rejection。

六、主题定制 ​

ts
// styles/element.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': ('base': #42b883),
  ),
);
ts
// vite.config.ts
css: {
  preprocessorOptions: {
    scss: { additionalData: `@use "@/styles/element.scss" as *;` },
  },
}

七、本章小结 ​

组件用途
el-table + el-pagination列表
el-dialog + el-form表单
el-menu菜单
el-message消息
主题 SCSS全局定制

动手练习 ​

  1. 用户列表:table + 分页 + 搜索
  2. 编辑表单:dialog + form + 校验
  3. 确认弹窗:删除前 ElMessageBox.confirm

下一章:第 24 章:表单与校验 →

本站基于 VitePress 构建 · 由 StackHub 团队维护