带你实现一个且或筛选条件组件(核心版)

需求

帮助不会写sql且或关系逻辑查询的用户,借助前端的且或过滤条件的交互,来实现类似后端的sql语句查询的功能。

前端数据结构分析

整个结构是一个条件数组,如下图是每一个条件的具体内容,即红色部分,分别为:event 、prop、condition、relation(且/或),condition为当前条件的核心,是这个过滤条件的细化,condition为一个条件数组,子数组的数据格式可以为A,也可以为B,也可以为任意个A和任意B的组合,其中组成B的最小单元又是A。

综上:可以得出如下的数据结构:

typescript 复制代码
export interface IFilterData {
  event: string // 事件
  prop: string //  属性/指标
  relation: string // condition的关系且/或
  condition: (IConditionA | IConditionB)[]
}
export interface IConditionA {
  prop: string //  属性/标签
  operator: string //操作:等于、不等于、包含等
  value: string // 值
}
export interface IConditionB {
  relation: string // condition的关系且/或
  condition?: IConditionA[]
}

组件拆分

1. 组件 1 (base-event-filter.vue)

红色部分为for循环一个过滤条件,蓝色部分为添加按钮,因此我们把红色拆为一个组件。整体HTML结构如下:

xml 复制代码
<div class="base-event-filter">
  <!-- 红色部分 -->
  <ItemFilter :data="filterData" />
  <!-- 蓝色部分 -->
  <span class="add_icon" @click="handleAdd">
    添加指标
  </span>
</div>
typescript 复制代码
<script lang="ts" setup>
  import ItemFilter from './item-filter.vue'
  interface IFilterData {
    event: string // 事件
    prop: string //  属性/指标
    relation: string // condition的关系且/或
    condition: (IConditionA | IConditionB)[]
  }
  type Props = {
    modelValue: IFilterData[]
  }
	const props = defineProps<Props>()
	const emit = defineEmits(['update:modelValue'])

  const filterData = ref(props.modelValue ?? [])
  
  const handleAdd = () => {
    filterData.value.push({ event: '',prop:'', condition: [], relation: '且' })
  }

  watch(filterData, (val) => {
    emit('update:modelValue', val)
  })
</script>

2. 组件拆分------ItemFilter.vue

仍重点讲红色部分,红色部分为我们数据结构的relation以及condition,relation比较好处理,就是一个css样式,点击用于切换条件直接的关系,核心是右侧的结构。

图片交互的数据结构可以描述如下:

csharp 复制代码
{
  event:'',
  prop:'',
  relation:'且',
  condition:[
    // IConditionB
    {
      relation:'或',
  		condition:[
      	{
          prop:'',
          operator:'',
          value:''
        },
  			{
          prop:'',
          operator:'',
          value:''
        }
      ]
    },
		// IConditionA
  	{
       	prop:'',
      	operator:'',
      	value:''
    }
  ]
}

我们把整体的红色部分拆为一个组件,因为这个组件还做了组件嵌套,也就是组件递归,我们把这个组件称为item-filter-child.vue。

3. 核心组件------item-filter-child.vue

HTML结构:

xml 复制代码
<div class="item-filter-child">
  <!-- relation -->
  <div v-if="currentData.condition?.length > 1" class="relation">
    <span>且</spa >
      <span>或</span>
  </div>
  <!-- 过滤条件 -->
  <div>
    <div
      v-for="(condition, conditionIndex) in currentData.condition"
      :key="conditionIndex"
      class="child-item"
      >
      <!-- IConditionA -->
      <template v-if="!condition.condition?.length || condition.condition.length === 1">
         <!-- prop、operator、value对应的HTML -->
      </template>
      <!-- IConditionB 递归组件本身 -->
      <ItemFilterChild v-else :data="condition"></ItemFilterChild>
    </div>
  </div>
</div>

总结

到此整个组件就完成了,本文主要讲述组件的实现方法、组件的拆分逻辑,以及递归组件的实现,希望能帮助到你。

相关推荐
雪芽蓝域zzs5 小时前
第 2 节:基础扩展 - 下拉弹窗常用原生属性
vue.js·elementui
扶风ff5 小时前
新品知识更新太快?用练题簿在线刷题,安排企业培训的小测与复盘
前端·学习·小程序
对空六课6 小时前
支持注意力分析的热力图工具有哪些?
前端·数据库·数据分析
Csvn7 小时前
Vue3 响应式与编译:依赖收集如何升级为节点级靶向更新
前端
星栈8 小时前
pnpm 12 升级实测
前端·javascript
Sirens.8 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
特创数字科技9 小时前
一个纯本地运行的图片处理工具:压缩 / 裁剪 / 九宫格 / 圆角 / 滤镜 / 拼图 / 水印,终生使用
前端
IT_陈寒10 小时前
Vue的v-if和v-for混用居然是个天坑
前端·人工智能·后端
天衍四九-10 小时前
【无标题】
前端·spring boot·mysql·nginx·docker
广州华水科技10 小时前
2026年单北斗GNSS变形监测系统推荐榜单,解锁GNSS位移监测新高度
前端