从零开始Vue3+Element Plus后台管理系统(八)——模仿禅道做一个Vue3版本的高级查询组件

image.png

暗黑模式

image.png

使用 Vue3+element Plus 简单模仿了禅道系统的高级搜索组件,说简单也有点复杂,还没有完全开发完,但是大体架子有了,剩下一些功能点继续coding。边开发边记录吧,因为这个相比之前的内容确实复杂一些,也更接地气。

大概的功能如下图

image.png

主要思路

这是一个相对复杂的组件,所以拆分成了多个文件,主要有3个:

  1. 主要区域,用于显示和设置搜索条件
  2. 右侧,保存的搜索方案,可以切换搜索方案(主区域的条件跟着变化)
  3. 保存搜索方案的弹窗

image.png

备选搜索项是一个数组,包含所有可选的条件,可以来自于接口,也可以前端自行定义,此处我在前端定义了几个数据用于DEMO演示

备选搜索项和默认搜索方案经过处理,获得一个初始展示的条件列表,如果列表有数据,那么就会展示默认设置的条件,表单内容显示为空。

当用户设置完搜索条件后,可以点击搜索,也可以保存到自定义的查询方案。查询方案保存在localstorage中

文件结构如下图

image.png

代码比较多,下面贴出来比较重要的部分。

主要搜索条件区域

搜索条件表单,默认是6个,数据通过备选搜索项和默认查询方案得来。

如果没有需要默认展示的条件,6个搜索条件都是空的,

// 备选参与搜素的项目
let listColumns = reactive<SearchColumnItem[]>([])
listColumns = demoList

// 初始渲染的搜索条件, 还未加入查询方案的影响
let defaultColumns = reactive<SearchColumnItem[]>(listColumns.filter((cur) => cur.default))
              <ul>
                <li
                  v-for="(i, index) in maxCount"
                  :key="i"
                  :class="index < showCount ? 'flex' : 'hidden'"
                >
                  <SearchItem
                    :columns="listColumns"
                    :defaultColumn="defaultColumns[index]"
                    :index="index"
                    :ref="(el:any) => setRef(el, index)"
                  />
                </li>
              </ul>

单个搜索条件继续拆分成子组件 SearchItem.vue

image.png

<template>
  <el-select v-if="index > 0" v-model="formData.andOr" class="mr-1 w-[80px] flex-shrink-0">
    <el-option v-for="ao in andOrOptions" :key="ao.value" :label="ao.label" :value="ao.value" />
  </el-select>

  <el-select class="mr-1 w-[150px] flex-shrink-0" v-model="formData.code" @change="changeCode">
    <el-option v-for="c in columns" :key="c.code" :label="c.label" :value="c.code" />
  </el-select>

  <el-select
    class="mr-1 w-[100px] flex-shrink-0"
    v-model="formData.condition"
    @change="changeCondition"
    ><el-option v-for="c in conditionOptions" :key="c.value" :label="c.label" :value="c.value"
  /></el-select>

  <component
    :disabled="disabled"
    class="flex-1"
    :is="ctOptions[formData.type as keyof typeof ctOptions]"
    v-model:value="formData.value"
  ></component>
</template>

其中component对应的是formComponents下的文件,在父组件中根据搜索项的配置,用component使用对应输入组件。

这些是用户输入的组件,之所以分成多个组件,一是简单清晰,而是方便扩展自定义组件。目前只放了几个基础的element plus的组件。

渲染搜索条件使用的数据格式如下,可以根据需要自行修改增加

export default [
  {
    label: '用户名',
    code: 'name',
    type: 'input',
    condition: 'equal',
    default: true
  },
...
]

export const andOrOptions = [
  {
    value: 'and',
    label: '并且'
  },
  {
    value: 'or',
    label: '或者'
  }
]

export const conditionOptions = [
  {
    value: 'equal',
    label: '等于'
  },
  {
    value: 'notEqual',
    label: '不等于'
  },
...
]
多个同名ref的处理

点击搜索时,会获取6个子组件的数据,组合成searchParams,Vue2中我们可以使用多个同名ref,然后使用this.$refs来遍历数据,Vue3在循环生成ref时和Vue2有一些不同,稍稍麻烦一点。

不过这里我又小小卡住了一会———开始setRef方法保存的是对象,结果每次点击搜索按钮,itemRefs数组的length就翻一倍,无解,最后该用现在的写法使用数组保存,保证ref不会超出预期数量。


<SearchItem
                :columns="listColumns"
                :defaultColumn="defaultColumns[index]"
                :index="index"
                :ref="(el:any) => setRef(el, index)"
              />
              
              
...
              
let itemRefs: Array<any> = []
function setRef(el: HTMLElement | ComponentPublicInstance, index: number) {
  itemRefs[index] = el
}

// 搜索时遍历获取子组件数据
function search() {
  searchParams.params = []
  itemRefs.forEach((element) => {
    if (element?.formData?.code) {
      searchParams.params.push(element.formData)
    }
  })
}

只要捋清了各个功能点,合适拆分子组件,复杂的组件也可以变简单!

有了你的赞👍,我会更努力😄

本项目GIT地址:github.com/lucidity99/…

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

immocha

人生得意须尽欢

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

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

打赏作者

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

抵扣说明:

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

余额充值