vue3+ts+element-plus 列表查询条件/筛选条件组件二次封装(条件查询组件新增每行显示多少项/收起时设置默认展示行数)

2024-06-05 条件查询组件新增每行显示多少项,效果如下:

在这里插入图片描述

2024-06-05 条件查询组件收起时设置默认展示行数,效果如下:

在这里插入图片描述

一、需求

对于后台管理系统项目必不可少的就是 “增删改查”;而 “查”,就会根据表格的列数来显示多少个查询/筛选条件;为了方便因此封装了查询条件(筛选条件)组件

二、组件功能

1、自动排列布局,每行显示4列(即4个条件)
2、内置“查询”和“重置”操作,并且按钮始终居于查询条件的最右侧
3、特定查询条件(如日期范围),可以配置占2列(span属性)
4、自动填入placeholder(日期范围除外)也可以自定义填入
5、默认输入框清空功能及下拉选择可以搜索选择功能
6、可以设置联调功能
7、可以自定义label
8、可以自定义输入框插槽
9、可以自定义 class
10、可以继承引入第三方组件的属性(属性写在bind:{}里面——bind也可以是function11、可以继承引入第三方组件的事件(事件写在eventHandle:{}里面)
12、条件过多有收起&展开功能
13、收起默认展示多少条
14、查询条件每行展示多少项(默认4项)

三、最终效果

在这里插入图片描述

四、参数配置

1、代码示例

<t-query-condition :opts="opts" @submit="conditionEnter" @handleEvent="handleEvent" :loading="loading" />
<!-- opts:配置项
     @submit:点击查询按钮 返回最终数据
     @handleEvent:每个查询条件的event:string,输入的值
     loading:查询按钮loading -->

1、配置参数(Attributes)

参数说明类型默认值
opts接收筛选器组件配置object
loading查询按钮 loading 状态,请求数据时需要体现Booleanfalse
reset是否显示“重置”按钮Booleantrue
boolEnter是否敲回车查询Booleantrue
isShowOpen是否显示收起和展开Booleantrue
isExpansion是否默认展开Booleanfalse
labelWidthlabelWidth 宽度String‘110px’

2、opts Attributes

参数说明类型默认值
label表单字段说明标题string-
className自定义 classstring-
placeholderplaceholder 提示语string-
labelRender自定义 label(render 函数 jsx 方式编写)function-
slotName自定义输入框插槽(作用域插槽解构接收{param}返回当前所有表单初始值)string-
comp组件名称,可直接指定全局注册的组件,也可引入’elmentUI’如:Button 或者’el-button’string,component-
span控件占用的列宽,默认占用 1 列,最多 4 列 (独占一行)number1
defaultVal默认值--
bind渲染时组件会调用 v-bind 指定设置该配置更新元素的属性(继承第三方组件属性)object,function
eventHandle配置组件事件,与写组件时change 等同理object本身值,当前formData数据

3. 事件(events)

事件名说明返回值
handleEvent筛选器数据发生变化时触发event标识, val:输入值,form:整个查询条件数据
submit点击筛选器查询按钮时触发form:整个查询条件数据
reset点击筛选器重置按钮时触发-

4、Slots

插槽名说明
querybar按钮操作插槽(位置基于重置后面)

五、具体代码

<template>
  <el-form
    id="t_query_condition"
    v-bind="$attrs"
    :label-width="labelWidth"
    :form="state.form"
    size="default"
    class="t-query-condition"
    :style="{
      'grid-template-areas': gridAreas,
      'grid-template-columns': `repeat(${colLength}, minmax(220px, ${
        100 / colLength
      }%))`,
    }"
    @submit.prevent
  >
    <el-form-item
      v-for="(opt, i) in cOpts"
      :key="i"
      :label="opt.label"
      :label-width="opt.labelWidth"
      v-bind="$attrs"
      :style="{ gridArea: i }"
      :class="[opt.className, { render_label: opt.labelRender }]"
    >
      <!-- 自定义label -->
      <template #label v-if="opt.labelRender">
        <render-comp :form="state.form" :render="opt.labelRender" />
      </template>
      <!-- 自定义输入框插槽 -->
      <template v-if="opt.slotName">
        <slot :name="opt.slotName" :param="state.form"></slot>
      </template>
      <component
        v-if="!opt.slotName && opt.comp.includes('date')"
        :is="opt.comp"
        v-bind="
          typeof opt.bind == 'function'
            ? opt.bind(state.form)
            : { clearable: true, filterable: true, ...$attrs, ...opt.bind }
        "
        :placeholder="opt.placeholder || getPlaceholder(opt)"
        @change="handleEvent(opt.event, state.form[opt.dataIndex])"
        v-model="state.form[opt.dataIndex]"
      />
      <component
        v-if="!opt.slotName && opt.comp.includes('tree-select')"
        :is="opt.comp"
        v-bind="
          typeof opt.bind == 'function'
            ? opt.bind(state.form)
            : { clearable: true, filterable: true, ...$attrs, ...opt.bind }
        "
        :placeholder="opt.placeholder || getPlaceholder(opt)"
        @change="handleEvent(opt.event, state.form[opt.dataIndex])"
        v-model="state.form[opt.dataIndex]"
      />
      <component
        v-if="
          !opt.slotName &&
          !opt.comp.includes('date') &&
          !opt.comp.includes('tree-select')
        "
        :is="opt.comp"
        v-bind="
          typeof opt.bind == 'function'
            ? opt.bind(state.form)
            : { clearable: true, filterable: true, ...$attrs, ...opt.bind }
        "
        :placeholder="opt.placeholder || getPlaceholder(opt)"
        @change="handleEvent(opt.event, state.form[opt.dataIndex])"
        v-on="cEvent(opt)"
        v-model="state.form[opt.dataIndex]"
      >
        <component
          :is="compChildName(opt)"
          v-for="(value, key, index) in selectListType(opt)"
          :key="index"
          :disabled="value.disabled"
          :label="compChildLabel(opt, value)"
          :value="compChildValue(opt, value, key)"
          >{{ compChildShowLabel(opt, value) }}</component
        >
      </component>
    </el-form-item>
    <el-form-item
      v-if="Object.keys(cOpts).length > 0"
      label-width="0"
      style="grid-area: submit_btn"
      :class="['btn', { flex_end: cellLength % colLength === 0 }]"
    >
      <el-button
        class="btn_check"
        @click="checkHandle"
        v-bind="queryAttrs"
        :loading="loading"
        >查询</el-button
      >
      <el-button
        v-if="reset"
        class="btn_reset"
        v-bind="resetAttrs"
        @click="resetHandle"
        >重置</el-button
      >
      <slot name="querybar"></slot>
      <el-button
        v-if="originCellLength > colLength && isShowOpen"
        @click="open = !open"
        link
      >
        {{ open ? '收起' : '展开' }}
        <el-icon v-if="open">
          <ArrowUp />
        </el-icon>
        <el-icon v-else>
          <ArrowDown />
        </el-icon>
      </el-button>
    </el-form-item>
  </el-form>
</template>

六、组件地址

gitHub组件地址

gitee码云组件地址

vue3+ts基于Element-plus再次封装基础组件文档

七、相关文章

基于ElementUi再次封装基础组件文档


vue+element-ui的列表查询条件/筛选条件组件二次封装

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现搜索功能,首先需要在 Pinia 中定义一个 store,用于存储搜索相关的状态和数据。示例代码如下: ```typescript import { defineStore } from 'pinia'; interface SearchState { keyword: string; results: any[]; // 存储搜索结果 } export const useSearchStore = defineStore({ id: 'search', state: (): SearchState => ({ keyword: '', results: [], }), getters: { hasResults(state): boolean { return state.results.length > 0; }, }, actions: { search(keyword: string) { // 发起搜索请求,获取搜索结果 // 这里可以使用 axios 或其他类库,获取后端接口返回的数据 const results = [{ title: '搜索结果1' }, { title: '搜索结果2' }]; this.keyword = keyword; this.results = results; }, clearResults() { this.results = []; }, }, }); ``` 在组件中使用该 store,需要使用 `useStore` 方法获取 store 实例,然后在模板中绑定输入框和搜索按钮的事件。示例代码如下: ```vue <template> <div> <input v-model="keyword" placeholder="输入关键字" /> <button @click="handleSearch">搜索</button> <ul v-if="hasResults"> <li v-for="result in results" :key="result.title">{{ result.title }}</li> </ul> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { useStore } from 'pinia'; import { useSearchStore } from './searchStore'; export default defineComponent({ setup() { const store = useStore(useSearchStore); const keyword = store.keyword; const results = store.results; const hasResults = store.hasResults; const handleSearch = () => { store.search(keyword); }; return { keyword, results, hasResults, handleSearch, }; }, }); </script> ``` 在模板中,我们使用了 `v-model` 指令绑定了输入框的值,使用 `@click` 绑定了搜索按钮的点击事件。在 `setup` 中使用 `useStore` 方法获取了 store 实例,并将 store 中的状态和方法绑定到模板中使用。在 `handleSearch` 方法中,调用了 store 的 `search` 方法,发起了搜索请求,更新了 store 中的状态,从而触发了模板中对应的响应式状态的更新。最终,我们根据 store 中的状态来展示搜索结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wocwin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值