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

需求

帮助不会写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>

总结

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

相关推荐
小码哥_常几秒前
被EdgeToEdge适配折磨疯了,谁懂!
前端
小码哥_常12 分钟前
从Groovy到KTS:Android Gradle脚本的华丽转身
前端
灵感__idea22 分钟前
Hello 算法:复杂问题的应对策略
前端·javascript·算法
麦麦鸡腿堡1 小时前
JavaWeb_请求参数,设置响应数据,分层解耦
java·开发语言·前端
Dxy12393102162 小时前
CSS常用样式详解:从基础到进阶的全面指南
前端·css
IT_陈寒2 小时前
SpringBoot自动配置揭秘:5个让开发效率翻倍的隐藏技巧
前端·人工智能·后端
Moment2 小时前
前端工程化 + AI 赋能,从需求到运维一条龙怎么搭 ❓❓❓
前端·javascript·面试
Joker Zxc2 小时前
【前端基础(Javascript部分)】6、用JavaScript的递归函数和for循环,计算斐波那契数列的第 n 项值
开发语言·前端·javascript
Highcharts.js2 小时前
React 图表如何实现下钻(Drilldown)效果
开发语言·前端·javascript·react.js·前端框架·数据可视化·highcharts
橙露3 小时前
Webpack/Vite 打包优化:打包体积减半、速度翻倍
前端·webpack·node.js