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

需求

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

总结

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

相关推荐
轻口味3 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami6 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡40 分钟前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O1 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235951 小时前
web复习(三)
前端
迷糊的『迷』1 小时前
vue-axios+springboot实现文件流下载
vue.js·spring boot
web135085886351 小时前
uniapp小程序使用webview 嵌套 vue 项目
vue.js·小程序·uni-app