【vue/组件封装】封装一个带条件筛选的搜索框组件(多组条件思路、可多选)详细流程

引入:实现一个带有筛选功能的搜索框,封装成组件;

搜索框长这样子:
在这里插入图片描述
点击右侧筛选图标后弹出层,长这样子:
在这里插入图片描述
实际应用中有多组筛选条件,这里为了举栗子就展示一组;

预览:
请添加图片描述

实现思路

  1. css 样式大致布局;
  2. 选中和取消选中的效果、样式切换等;
  3. 多选的功能;
  4. 多组筛选条件的多选功能;

需要给父组件传递的数据有:

  • 点击搜索按钮时传【输入的内容】;
  • 点击查询按钮时传【选择的查询条件】

进一步的实现:

  • 首先写好基础的静态样式;
  • 当要开始写功能的时候,可以换成接口调用的动态数据,从父组件传入;
  • 先写单选,动态绑定 class 样式来实现选中之后的样式:
:class="{ 'seled-btn': venSeled.includes(index) }"
  • 选中后考虑还需要取消,因为条件筛选是多选的,所以是将下标保存进数组中:
if (this.typeSeled.includes(index)) {
    // 筛掉【当前选中的】和【数组中】不一致的下标,即只保存相等的
    this.typeSeled = this.typeSeled.filter(item => item != index)
} else {
    // 未选中就添加进数组中
    this.typeSeled.push(index)
}

代码:

<!-- 
    带条件筛选的搜索框组件
 -->

<template>
    <view class="container">
        <u-popup v-model="show" mode="top" border-radius="14" length="50%">
            <view class="wrap">
                <view class="wrap-top">
                    <p>类型:</p>
                    <view class="item">
                        <view v-for="(item, index) in typeList" :key="index" @click="seledBtn(index, 'type', item)"
                            class="btn sel-btn" :class="{ 'seled-btn': typeSeled.includes(index) }">{{ item }}
                        </view>
                    </view>
                </view>
            </view>
            <view class="wrap-foot" style="display: flex;">
                <u-button @click="reset">重置</u-button>
                <u-button type="primary" @click="searchRes">查询</u-button>
            </view>
        </u-popup>
        <u-search @custom="searchClick" :show-action="true" v-model="val" placeholder="请输入" shape="square"
            :border="border" :animation="false"></u-search>
        <img class="right-icon" @click="show = true" src="../../../../static/gzt/filter.png" width="18" height="18" alt="">
    </view>
</template>

<script>
export default {
    props: {
        vehList: {
            type: Array
        },
        workList: {
            type: Array
        }
    },
    data() {
        return {
            typeList: ['类型1', '类型2'],
            // 是否点击
            typeSeled: [],
            val: '',
            border: true,
            show: false
        }
    },
    methods: {
        // 点击搜索
        searchClick() {
            this.$emit('singleClick', this.val)
        },
        // 选中某一个条件
        seledBtn(index, type, itemVal) {
            // console.log('type', type);
            if (type == 'type') {
                if (this.typeSeled.includes(index)) {
                    // 筛掉【当前选中的】和【数组中】不一致的下标
                    this.typeSeled = this.typeSeled.filter(item => item != index)
                } else {
                    // 未选中就添加进数组中
                    this.typeSeled.push(index)
                }
            } 
        },
        // 点击重置
        reset() {
            this.typeSeled = []
        },
        // 点击查询
        searchRes() {
            let typeRes = []

            // 整理数据
            // typeList typeSeled
            this.typeList.forEach((item, index) => {
                this.typeSeled.forEach(item1 => {
                    if (index == item1) {
                        typeRes.push(item)
                    }
                })
            })
            // 给父组件发送选择的查询条件
            this.$emit('filterSearch', typeRes)
        }
    }
}
</script>

样式参考:

<style lang="scss">
.wrap {
    padding: 0 15px 60px 15px;

    // background-color: pink;
    .wrap-top {
        margin-top: 10px;

        >p {
            color: #4F4B46;
        }

        .item {
            display: flex;
            flex-wrap: wrap;
            margin-top: 10px;
        }

        // btn的共有样式
        .btn {
            margin-top: 5px;
            margin-right: 8px;
            width: 30%;
            text-align: center;
            padding: 5px;
            border-radius: 8px;
        }

        // 未被选中的样式
        .sel-btn {
            background-color: #F5F7F8;
            color: #717171;
            border: 1px solid #F0F0F0;

        }

        // 被选中的样式
        .seled-btn {
            background-color: #EDF5FF;
            border: 1px solid #6AA4EC;
            color: #6AA4EC;
        }
    }
}

::v-deep .u-btn--default {
    color: #b7b8b8 !important;
    border-radius: 0px;
}

.wrap-foot {
    position: fixed;
    margin-top: 5px;
    bottom: -1px;
    width: 100%;
}

::v-deep uni-button {
    width: 100%;
}

.container {
    display: flex;
    background-color: white;
    padding: 5px;
    border-radius: 8px;

    .right-icon {
        margin-top: 7px;
        margin-left: 10px;
    }
}

::v-deep .u-action-active {
    color: gray;
}

::v-deep .u-content {
    border: 1px solid #ccc !important;
}
</style>

关于有好几组筛选条件时怎么进行选择,我的方法是,在 seledBtn 函数里写一个循环,以 0-几组筛选条件的长度进行循环,最终数组只有一个,给这个数组里对应下标里进行增加或删除,下标对应的是第几组筛选条件,比如我有3组,最终数组就是:[[],[],[]] 这么一个嵌套数组;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

花间半盘棋

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值