普通视图

发现新文章,点击刷新页面。
昨天 — 2026年1月29日首页

【配置化 CRUD 01】搜索重置组件:封装与复用

作者 大杯咖啡
2026年1月29日 18:03

一:前言

在后台管理系统的配置化 CRUD 开发中,搜索+重置是高频组合场景,几乎所有列表页都需要通过搜索筛选数据、通过重置恢复初始查询状态等等...。基于此,本文将详细讲解「搜索重置组件」的封装思路及使用方法,该组件基于Vue3 + Element Plus 开发,支持配置化扩展、响应式联动,可直接集成到配置化 CRUD 体系中,提升开发效率与代码一致性。

二:解决问题

封装搜索重置组件主要为了解决以下几个问题:

1.代码冗余 : 每个列表页都要重复编写表单结构、搜索按钮、重置按钮,以及对应的点击事件、数据校验逻辑;

2.风格不统一:不同开发人员编写的搜索表单,在布局、按钮尺寸、标签宽度、间距等细节上可能存在差异;

3.维护成本高:当需要修改搜索表单的布局、按钮样式,需要逐个页面排查修改;

...

三:具体实现

在开始之前,请先阅读一下本专栏的第一篇文章,动态表单的实现是搜索重置组件的基础:

juejin.cn/post/757946…

image.png

接下来我们可以思考一下一个通用的搜索重置组件具备的基本功能

1.搜索项的展示

2.搜索项默认展示搜索初始值

3.搜素与重置按钮功能

...

扩展功能:

1.搜索表单项的联动

2.搜索表单项的校验

...

接下来我们一步一步来实现:

3.1 基础功能实现

先完成最简单的部分 : 展示搜索项和搜索重置按钮、以及基本样式统一处理

组件基础实现:


type SearchPrams = {
  schema?: FormOptions[] // 配置表
  search?: () => void  // 搜索回调
  reset?: () => void   // 重置回调
  labelWidth?: string,
  flex?: number
}
const props = withDefaults(defineProps<SearchPrams>(), {
  schema: {},
  labelWidth:'140px',
  flex:5
})

const codeFormRef = ref(null)

//搜索
const search = async () => {
  const data = await codeFormRef?.value?.getData()
  emits('search', data)
}

//重置
const reset = () => {
  codeFormRef?.value?.resetFields('')
  emits('reset', {})
}

 <div class="sea-box">
    <CodeForm
      class="form-box"
      :style="{ flex: props?.flex || 5 }"
      layoutType="cell"
      ref="codeFormRef"
      :schema="schema"
      :labelWidth="props.labelWidth"
    >
    </CodeForm>
    <div class="sea-btn-box">
      <div>
        <ElButton
          type="primary"
          :style="{ width: '80px' }"
          @click="search"
          >{{ $t('Search') }}</ElButton
        >
        <ElButton
          :style="{ width: '80px', marginLeft: '15px' }"
          @click="reset"
          >{{ $t('Reset') }}</ElButton
        >
      </div>
    </div>
  </div>
  
 <style scoped>
    .sea-btn-box {
      flex: 1;
      display: flex;
      justify-content: flex-end;
    }
    .form-box {
      flex: 5;
    }
    .sea-box {
      display: flex;
      padding: 20px;
      padding-bottom: 0;
      padding-top: 0;
    }
</style>

外部定义配置表:

  const searchColumn = [
      {
        label: '姓名',
        prop: 'name',
        component: 'Input',
      },
      {
        label: '年龄',
        prop: 'age',
        component: 'Input',
      },
      {
        label: '上学阶段',
        prop: 'jieduan',
        component: 'Select',
        componentProps: {
            options: [
              {
                label: '幼儿园',
                value: 1
              },
              {
                label: '其他阶段',
                value: 2
              }
            ]
          }
      },
]

引入组件使用:

 <Search
    :schema="allshema.searchcolumns"
    @search="(params) => console.log('点击查询:',{params})"
    @reset="() => setSearchParams({}, true, true)"
   >
</Search>

运行截图:

image.png

到这一步我们就已经实现了基本功能:展示表单、统一风格、查询重置

当然我们可能会想要某些表单项具有初始值,或者不展示重置按钮,只要组件内部稍加改造一下就行:


type SearchPrams = {
  showSearch?: boolean // 展示搜索按钮
  showReset?: boolean // 展示重置按钮
  schema?: any // 配置表
  search?: () => any
  reset?: () => any
  labelWidth?: string,
  flex?: number
}

 <div class="sea-btn-box">
      <div>
        <ElButton
          v-if="showSearch"
          type="primary"
          :style="{ width: '80px' }"
          @click="search"
          >{{ $t('Search') }}</ElButton
        >
        <ElButton
          v-if="showReset"
          :style="{ width: '80px', marginLeft: '15px' }"
          @click="reset"
          >{{ $t('Reset') }}</ElButton
        >
      </div>
 </div>

外部引入:

const searchColumn = [
      {
        label: '姓名',
        prop: 'name',
        initValue: '初始化名字',
        component: 'Input',
      },
      ...
  ]
  <Search
     :schema="searchColumn"
     @search="(params) => console.log('点击查询:',{params})"
     :showReset="false"
    >
 </Search>
 

运行截图:

image.png

这样就实现了按钮的展示与隐藏以及初始化默认值。

3.2 扩展功能实现

接下来我们继续实现一下扩展功能:

1.表单项的联动

利用动态表单组件内置的 setValues、setSchemas方法,

组件内部增加方法定义及暴露:


const setValues = (data: any) => {
  codeFormRef?.value?.setValues(data)
}

const setSchemas = (data: any) => {
  codeFormRef?.value?.setSchemas(data)
}

defineExpose({
  getData,
  setValues,
  setSchemas
})

外部增加搜索组件的ref引用:

const searchRef: any = ref(null)

const searchColumn = [
  {
    label: '姓名',
    prop: 'name',
    initValue: '初始化名字',
    component: 'Input',
    componentProps: {
      onInput: (e: any) => {
         console.log('姓名输入框输入事件', e)
         searchRef.value?.setSchemas([
             {
                prop: 'age',
                path: 'componentProps.placeholder',
                value: `请输入${e}的年龄`
            }
         ])
      }
    }
  },
  {
    label: '年龄',
    prop: 'age',
    component: 'Input',
  },
  ...
]

<Search
   ref="searchRef"
   :schema="allshema.searchcolumns"
   @search="setSearchParams"
   @reset="() => setSearchParams({}, true, true)"
  >
</Search>

运行截图:

image.png

这样就实现了搜索表单项之间的联动。

2.表单项的校验

组件内部改动:

type SearchPrams = {
  showSearch?: boolean // 展示搜索
  showReset?: boolean // 展示重置按钮
  isVaildSearch?: boolean // 是否校验搜索
  schema?: any // 配置表
  search?: () => any
  reset?: () => any
  labelWidth?: string,
  flex?: number
}

const props = withDefaults(defineProps<SearchPrams>(), {
  showSearch: true,
  showReset: true,
  isVaildSearch: false,
  schema: {}, // 表单配置
  labelWidth:'140px',
  flex:5
})

const search = async () => {
  if(props.isVaildSearch) {
    const valid = await codeFormRef?.value?.validate();
    if(!valid) return;
  }
  const data = await codeFormRef?.value?.getData()
  emits('search', data)
}

外部引入使用:

const searchColumn = [
    ...,
    {
       label: '年龄',
       prop: 'age',
       component: 'Input',
       formItemProps: {
         rules:[
             {
               required: true,
               message: '请输入年龄',
               trigger: 'blur'
             }
          ]
       }
    },
    ...
]

<Search
    ref="searchRef"
    :schema="searchColumn"
    @search="(params) => console.log('点击查询:',{params})"
    :showReset="false"
    :isVaildSearch="true"
   >
</Search>

运行截图:

image.png

这样就实现了搜索表单项的表单校验。

以上就是搜索重置组件的核心实现步骤~

❌
❌