基于element的自定义组件实现前端自定义sql查询条件

组件功能概述

InputSelect 是一个结合了输入框 (el-input) 和下拉选择框 (el-select) 的复合组件。用户可以先选择一个条件类型,然后输入相应的值。这个组件特别适合用于表单中的高级搜索或过滤场景。

优化版====>>>基于element的自定义组件实现前端自定义sql查询条件(改良版)
优化后版本使用更简单,无需在父组件内创建方法处理数据变动

组件效果

在这里插入图片描述

数据请求格式

在这里插入图片描述

后端逻辑可参考(以mybatis为例)

 <if test="query.matchList != null and query.matchList.size() > 0">
            <foreach collection="query.matchList" separator="AND" item="condition">
                <choose>
                    <!-- 精确匹配 -->
                    <when test="condition.value == 'eq'">
                        AND ${columnName} = #{columnValue}
                    </when>
                    <!-- 不匹配 -->
                    <when test="condition.value == 'notEq'">
                        AND ${columnName} != #{columnValue}
                    </when>
                    <!-- 包含 -->
                    <when test="condition.value == 'like'">
                        AND ${columnName} LIKE CONCAT('%', #{columnValue}, '%')
                    </when>
                    <!-- 不包含 -->
                    <when test="condition.value == 'notLike'">
                        AND ${columnName} NOT LIKE CONCAT('%', #{columnValue}, '%')
                    </when>
                    <!-- 开头是 -->
                    <when test="condition.value == 'left'">
                        AND ${columnName} LIKE CONCAT(#{columnValue}, '%')
                    </when>
                    <!-- 结尾是 -->
                    <when test="condition.value == 'right'">
                        AND ${columnName} LIKE CONCAT('%', #{columnValue})
                    </when>
                    <!-- 为空 -->
                    <when test="condition.value == 'isNull'">
                        AND ${columnName} IS NULL
                    </when>
                    <!-- 不为空 -->
                    <when test="condition.value == 'notNull'">
                        AND ${columnName} IS NOT NULL
                    </when>
                    <!-- 空文本 -->
                    <when test="condition.value == 'isBlank'">
                        AND (${columnName} = '' OR ${columnName} IS NULL)
                    </when>
                    <!-- 非空文本 -->
                    <when test="condition.value == 'notBlank'">
                        AND (${columnName} != '' AND ${columnName} IS NOT NULL)
                    </when>
                    <!-- 其他情况 -->
                    <otherwise>
                        <!-- 处理未匹配到的情况,通常为空或报错 -->
                    </otherwise>
                </choose>
            </foreach>
        </if>

组件结构

InputSelect 组件主要由以下部分组成:

  • 模板: 包含一个 el-input 和嵌套在其内的 el-select
  • 数据: 定义了下拉选项、禁用类型、当前选择的类型和值。
  • 监听器: 监听外部传入的 items 变化,以同步更新组件状态。
  • 方法: updateItem 方法用于处理输入变化,并更新组件状态及通知父组件。

组件相关代码

<template>
  <div>
    <el-input placeholder="请输入"
              v-model="value"
              class="input-with-select"
              clearable
              :disabled="disabledType.includes(type)"
              @input="updateItem">
      <el-select slot="prepend"
                 placeholder="请选择"
                 style="width: 110px"
                 clearable
                 v-model="type"
                 @change="updateItem">
        <el-option-group v-for="group in options"
                         :key="group.label">
          <el-option v-for="item in group.options"
                     :key="item.value"
                     :label="item.label"
                     :value="item.value">
          </el-option>
        </el-option-group>
      </el-select>
    </el-input>
  </div>
</template>

<script>
/**
 * *****使用方法*****
 *
 * 在父组件中添加引用
 *
 * <input-select name="remark" :items="queryParams.items" @items-updated="onItemsUpdated"/>
 *
 * 并在methods中添加</br>
 *
 * onItemsUpdated(items) { this.queryParams.items = items; },
 */
export default {
  name: 'InputSelect',
  props: {
    items: {
      type: Array,
      default: () => []
    },
    name: {
      type: String,
      default: null
    }
  },
  data() {
    return {
      options: [
        {label: 'e', options: [{value: 'eq', label: '精确匹配'}, {value: 'notEq', label: '不匹配'}]},
        {label: 'l', options: [{value: 'like', label: '包含'}, {value: 'notLike', label: '不包含'}]},
        {label: 'll', options: [{value: 'left', label: '开头是'}, {value: 'right', label: '结尾是'}]},
        {label: 'n', options: [{value: 'isNull', label: '为空'}, {value: 'notNull', label: '不为空'}]},
        {label: 'b', options: [{value: 'isBlank', label: '空文本'}, {value: 'notBlank', label: '非空文本'}]}
      ],
      disabledType: ['isNull', 'notNull', 'isBlank', 'notBlank'],
      type: 'eq',
      value: ''
    }
  },
  watch: {
    items: {
      handler(newItems) {
        // 当items发生变化时,更新内部的状态
        const foundItem = newItems.find(item => item.name === this.name);
        if (foundItem) {
          this.type = foundItem.type;
          this.value = foundItem.value;
        } else {
          this.type = 'eq';
          this.value = '';
        }
      },
      deep: true
    }
  },
  methods: {
    updateItem() {
      if (this.disabledType.includes(this.type)) {
        this.value = '';
      }
      // 更新单个项的信息
      const item = {name: this.name, value: this.value, type: this.type};

      // 移除已存在的相同属性名称的项
      const existingItemIndex = this.items.findIndex(i => i.name === this.name);
      if (existingItemIndex > -1) {
        this.items.splice(existingItemIndex, 1);
      }

      // 检查是否所有必需的属性都有值
      if (item.name && item.type && (item.value || this.disabledType.includes(item.type))) {
        // 添加新的项
        this.items.push(item);

        // 通知父组件更新
        this.$emit('items-updated', this.items);
      }
    }
  }
}
</script>
<style scoped>
</style>

使用方法

3.1 引入组件

首先,在父组件中引入并注册 InputSelect 组件。

<template>
  <div>
    <!-- 引入 InputSelect 组件 -->
    <input-select name="remark" :items="queryParams.items" @items-updated="onItemsUpdated"/>
  </div>
</template>

<script>
import InputSelect from './InputSelect.vue';
</script>
3.2 配置组件

配置 InputSelect 组件时,需要传递以下属性:

  • name: 输入框的名称,用于区分不同的输入选择组件。
  • items: 一个数组,用于存储组件的状态信息(名称、类型、值)。

同时,需要定义一个方法 onItemsUpdated 来接收更新后的 items 数组。

// 父组件中定义的方法
export default {
  components: {
    InputSelect
  },
  data() {
    return {
      queryParams: {
        items: []
      }
    };
  },
  methods: {
    onItemsUpdated(updatedItems) {
      this.queryParams.items = updatedItems;
    }
  }
};

示例

假设我们需要一个用于搜索备注字段的输入选择组件,我们可以这样使用:

<template>
  <div>
    <input-select name="remark" :items="queryParams.items" @items-updated="onItemsUpdated"/>
  </div>
</template>

<script>
import InputSelect from './InputSelect.vue';

export default {
  components: {
    InputSelect
  },
  data() {
    return {
      queryParams: {
        items: []
      }
    };
  },
  methods: {
    onItemsUpdated(updatedItems) {
      this.queryParams.items = updatedItems;
    }
  }
};
</script>

当用户选择了条件类型(例如“精确匹配”)并输入了一个值后,InputSelect 组件会自动更新 items 数组,并通过 @items-updated 事件通知父组件进行后续处理。

结语

通过上述步骤,我们可以轻松地在 Vue.js 应用中集成 InputSelect 组件,从而提高表单的交互性和功能性。希望这篇分享能帮助到正在寻找类似解决方案的开发者们!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值