Skip to content

ProSearchForm 搜索表单

ProSearchForm 是一个基于 Vue 3.4+ 的动态搜索/筛选表单组件,支持配置驱动生成表单项、受控数据管理(v-model)、字段和操作区插槽自定义,适用于后台管理系统、数据筛选等场景。


组件特性

  • 配置驱动:通过 fields 数组自动生成表单项。
  • 受控模式:表单数据由父组件通过 v-model 完全控制。
  • 插槽灵活:支持字段级插槽和操作区插槽,满足高度自定义需求。
  • 事件友好:支持标准的提交和重置事件。
  • 类型安全:使用 Vue 3.4+ 新特性,开发体验更好。

代码示例

基础用法


搭配 ProTable + useList 使用

ProSearchForm 通常与 ProTableuseList 组合,实现完整的数据筛选、分页功能。


字段插槽自定义

你可以通过具名插槽自定义某个字段的渲染方式。


操作区插槽自定义

你可以通过 actions 插槽自定义操作按钮区。


Props

属性名类型默认值说明
fieldsField[][]表单字段配置数组
v-modelRecord<string, any>-表单数据,受控模式

Field 类型说明

ts
interface Field {
  name: string                // 字段名(对应表单数据 key)
  label: string               // 字段标签
  component?: string          // 表单项组件类型(如 'a-input', 'a-select')
  props?: Record<string, any> // 组件属性
}

Slots

插槽名说明
actions操作区插槽,参数:formState, handleSubmit, handleReset
字段名字段级插槽,参数:value, field

Events

事件名参数类型说明
submitRecord<string, any>表单提交时触发,返回表单数据
reset表单重置时触发

重要说明

重置行为

handleReset() 会将所有表单字段重置为空字符串 '',而不是 undefined

typescript
// 重置后的效果
searchForm.value = {
  name: '',      // 空字符串
  age: '',       // 空字符串
  status: ''     // 空字符串
}

如果你需要自定义重置行为,可以监听 @reset 事件:

vue
<ProSearchForm
  v-model="searchForm"
  :fields="fields"
  @reset="handleCustomReset"
/>

<script setup>
function handleCustomReset() {
  // 自定义重置逻辑
  searchForm.value = {
    name: '',
    age: undefined,  // 或者其他默认值
    status: null
  }
}
</script>

字段插槽的正确用法

字段插槽接收 { value, field } 参数,但 value 不是响应式的,不能直接用于 v-model

❌ 错误用法

vue
<template #age="{ value }">
  <a-slider v-model:value="value" />  <!-- ❌ value 不是响应式 -->
</template>

✅ 正确用法

vue
<template #age="{ field }">
  <!-- 直接使用 searchForm[field.name] -->
  <a-slider v-model:value="searchForm[field.name]" />
</template>

<!-- 或者直接使用字段名 -->
<template #age>
  <a-slider v-model:value="searchForm.age" />
</template>

默认行为

  • 默认组件:如果不指定 component,默认使用 a-input
  • 默认布局:3 列布局(每个字段 span="8"
  • 默认间距:列间距 gutter="16"
  • 默认按钮:提供 "搜索" 和 "重置" 按钮

表单布局

组件使用 Ant Design Vue 的栅格系统(24 列),每个字段占 8 列(即 3 列布局):

vue
<a-row :gutter="16">
  <a-col :span="8">字段1</a-col>  <!-- 占 8/24 -->
  <a-col :span="8">字段2</a-col>  <!-- 占 8/24 -->
  <a-col :span="8">字段3</a-col>  <!-- 占 8/24 -->
</a-row>

如需调整布局,可以通过 CSS 或自定义字段实现。


最佳实践

✅ 推荐做法

  1. 使用 v-model

    vue
    <ProSearchForm v-model="searchForm" :fields="fields" />
  2. 配置驱动

    typescript
    const fields = [
      { name: 'username', label: '用户名', component: 'a-input' },
      { name: 'status', label: '状态', component: 'a-select', props: { options } }
    ]
  3. 事件处理

    vue
    <ProSearchForm
      @submit="loadData"    // 提交时加载数据
      @reset="handleReset"  // 重置时的额外逻辑
    />
  4. 与 useList 配合

    typescript
    const { loadData, reset } = useList({
      request: fetchData,
      filters: {
        state: searchForm,
        autoWatch: true,
        resetPageOnChange: true,
        debounce: 300
      },
      extra: {
        immediate: true
      }
    })
    
    <ProSearchForm
      v-model="searchForm"
      @submit="loadData"
      @reset="reset"
    />

⚠️ 注意事项

  1. 插槽中访问表单值

    • 使用 searchForm[field.name]searchForm.字段名
    • 不要直接使用插槽参数中的 value(非响应式)
  2. 重置行为

    • 默认重置为空字符串 ''
    • 如需自定义,监听 @reset 事件
  3. 字段组件

    • 必须支持 v-model:value
    • 常用组件:a-input, a-select, a-input-number, a-date-picker, a-range-picker

适用场景

  • ✅ 列表页的搜索/筛选栏
  • ✅ 高级筛选表单
  • ✅ 快速生成可配置的表单项
  • ✅ 需要自定义操作按钮或表单项的场景
  • ✅ 与 ProTable + useList 组合使用

相关文档