7.2elementplus的表单布局与模式

基础表单

复制代码
<template>
  <el-form 
    ref="ruleFormRef" 
    :model="form" 
    :rules="rules" 
    label-width="100px"
  >
    <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" placeholder="请输入邮箱" />
    </el-form-item>
    <el-form-item label="爱好">
      <!-- 注意: 爱好没有 prop, 所以不会参与 el-form 的校验 -->
      <el-checkbox-group v-model="form.hobby">
        <el-checkbox label="读书" />
        <el-checkbox label="音乐" />
        <el-checkbox label="电影" />
      </el-checkbox-group>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">提交</el-button>
      <el-button @click="resetForm(ruleFormRef)">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'

const ruleFormRef = ref() // 用于获取 el-form 实例

// 表单数据
const form = reactive({
  username: '',
  email: '',
  hobby: [] // 数组
})

// 校验规则
const rules = reactive({
  username: [
    { required: true, message: '请输入用户名', trigger: 'blur' },
    { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '请输入邮箱地址', trigger: 'blur' },
    { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
  ]
})

// 提交表单
const submitForm = async (formEl) => {
  if (!formEl) return;
  try {
    // validate 返回 Promise
    await formEl.validate()
    ElMessage.success('提交成功!')
    console.log('表单数据:', form)
  } catch (error) {
    ElMessage.error('校验失败!')
    console.log('校验失败:', error)
  }
}

// 重置表单
const resetForm = (formEl) => {
  if (!formEl) return;
  formEl.resetFields()
}
</script>

行内表单 (Inline Form)

复制代码
<template>
  <el-form :inline="true" :model="searchForm" class="demo-form-inline">
    <el-form-item label="用户名">
      <el-input v-model="searchForm.username" placeholder="用户名" />
    </el-form-item>
    <el-form-item label="状态">
      <el-select v-model="searchForm.status" placeholder="选择状态">
        <el-option label="全部" value="" />
        <el-option label="启用" value="1" />
        <el-option label="禁用" value="0" />
      </el-select>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { reactive } from 'vue'

const searchForm = reactive({
  username: '',
  status: ''
})

const onSubmit = () => {
  console.log('查询条件:', searchForm)
}
</script>

标签在上方的表单

复制代码
<template>
  <el-form 
    :model="form" 
    :rules="rules" 
    label-position="top" 
    label-width="100px"
  >
    <el-form-item label="项目名称" prop="projectName">
      <el-input v-model="form.projectName" />
    </el-form-item>
    <el-form-item label="项目描述" prop="description">
      <el-input v-model="form.description" type="textarea" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary">保存</el-button>
    </el-form-item>
  </el-form>
</template>

动态增减表单项

复制代码
<template>
  <el-form :model="dynamicForm" ref="dynamicFormRef">
    <el-form-item
      v-for="(domain, index) in dynamicForm.domains"
      :key="domain.key"
      :label="index === 0 ? '域名' : ''" <!-- 只为第一个显示标签 -->
      :prop="'domains.' + index + '.value'"
      :rules="{
        required: true, message: '域名不能为空', trigger: 'blur'
      }"
    >
      <el-input v-model="domain.value" style="width: 300px; margin-right: 10px;" />
      <el-button @click.prevent="removeDomain(domain)">删除</el-button>
    </el-form-item>
    <el-form-item>
      <el-button @click="addDomain">新增域名</el-button>
      <el-button type="primary" @click="submitDynamicForm(dynamicFormRef)">提交</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ref, reactive } from 'vue'

const dynamicFormRef = ref()
const dynamicForm = reactive({
  domains: [
    { value: '', key: Date.now() } // key 用于 v-for 的唯一性
  ]
})

const addDomain = () => {
  dynamicForm.domains.push({
    value: '',
    key: Date.now() + Math.random()
  })
}

const removeDomain = (item) => {
  const index = dynamicForm.domains.indexOf(item)
  if (index !== -1) {
    dynamicForm.domains.splice(index, 1)
  }
}

const submitDynamicForm = async (formEl) => {
  if (!formEl) return;
  try {
    await formEl.validate()
    ElMessage.success('提交成功!')
    console.log('动态表单数据:', dynamicForm.domains)
  } catch (error) {
    ElMessage.error('校验失败!')
  }
}
</script>

使用建议与最佳实践

  1. ref 是关键 : 务必给 el-form 添加 ref,以便调用 validate, resetFields 等方法。
  2. prop 必须匹配 model : el-form-itemprop 值必须是 model 对象中存在的属性名,且路径要正确(如嵌套对象用 user.name)。
  3. 合理使用 trigger : blur 适合必填和格式校验,避免用户输入时频繁报错。change 适合实时性要求高的校验(如密码强度)。
  4. resetFields 的陷阱 : 它重置的是组件初始化时的 model 值。如果需要重置到一个特定的值(比如空对象 {}),可以在调用 resetFields() 后手动设置 model,或者使用 clearValidate() 和手动清空数据。
  5. 异步校验 : 使用 asyncValidator 处理需要请求后端验证的场景(如用户名唯一性检查)。注意防抖。
  6. status-icon: 开启后,用户能更直观地看到输入状态。
  7. scroll-to-error: 对于长表单,开启此功能能提升用户体验。
  8. inline-message: 在空间紧凑的布局中,使用行内错误信息可以节省垂直空间。
  9. 自定义错误信息 : 使用 el-form-itemerror 属性或 slots 可以完全控制错误信息的显示。
  10. 组合使用 : el-form 可以与 el-row/el-col 结合,实现更复杂的响应式表单布局。

掌握 el-form 的数据绑定、校验机制和布局控制,是高效开发 Vue + Element Plus 应用的基础。它极大地简化了表单处理的复杂性。

相关推荐
Mintopia15 小时前
低代码平台如何集成 AIGC 技术?核心技术衔接点解析
前端·javascript·aigc
Mintopia15 小时前
Next.js + AI-SDK + DeepSeek:3 分钟建设属于你的 AI 问答 Demo
前端·javascript·next.js
小林rush21 小时前
深入 Vue3 编译原理:实现一个mini模板编译器
前端·vue.js·前端框架
水冗水孚21 小时前
每天进步一点点——学习高度过渡的四种方式
前端·javascript·css
山有木兮木有枝_1 天前
前端性能优化:图片懒加载与组件缓存技术详解
前端·javascript·react.js
子兮曰2 天前
现代滚动技术深度解析:scrollTo与behavior属性的应用与原理
前端·javascript·浏览器
然我2 天前
JavaScript 的 this 到底是个啥?从调用逻辑到手写实现,彻底搞懂绑定机制
前端·javascript·面试
林希_Rachel_傻希希2 天前
别再写 c=3 了!window 对象的隐藏规则
前端·javascript
子兮曰2 天前
深度解析Proxy与目标对象(definiteObject):原理、特性与10个实战案例
前端·javascript·node.js
我是日安2 天前
从零到一打造 Vue3 响应式系统 Day 11 - Effect:Link 节点的复用实现
前端·vue.js