背景

项目开发中遇到筛选项,并且几个页面都有使用,依次写,太过于繁琐

筛选项解构如下

封装全局组件fjj-content

<template>
<div class="fjj-content">
<ul class="flex-col fjj-list">
<li v-for="(item, index) in list" :key="index">
<!-- custom 单选、多选 item.isMutiple 是否支持多选 -->
<div v-if="item.type === 'custom'">
<!-- item.isMutiple true 多选 -->
<div class="flex-row">
<span class="label-box">{{ item.title }}:</span>
<ul class="flex-row tags-list items-center">
<!-- 选中默认项 -->
<li
:class="{ activeLi: item.defaultSelect }"
class="justify-center items-center"
@click="selectDefault(item.detailList, item.isMutiple, item)"
>
<span> {{ item.defaultLabel }}</span>
</li>
<!-- 多选项、单选项公用一个 -->
<li
v-for="(ele, eIndex) in item.detailList"
:key="eIndex"
:class="{ activeLi: ele.isSelected }"
class="justify-center items-center"
@click="selectMutiple(eIndex, item.key, item.isMutiple, item)"
>
<span> {{ ele.title }}</span>
</li>
<!-- 单选项,且有日期选择框的那种 -->
<div v-if="!item.isMutiple && item.childrenType == 'rangetime'">
<el-date-picker
v-model="item.dateTime"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD HH:mm:ss"
@change="changeDate($event, item.key, item)"
/>
</div>
</ul>
</div>
</div>
</li>
</ul>
</div>
</template> <script setup>
/***
* 筛选组件,当前支持多选、单选
* item.type (custom 单选、多选、rangetime 时间范围带时分秒、range 时间范围不带时分秒、rangenumber 数字范围)
* item.isMutiple 是否支持多选
* 筛选后返回格式{"listName1":[value,value](多选),"listName2":"value"(单选),...}
* rangenumber形式-可能为["",1]或[1,""]表示只有一个最大值或最小值
***/ // Props
defineProps({
list: {
type: Array,
default() {
return []
}
}
}) // Emit
const emit = defineEmits('resultConditon') // Result object
const result = {} // 选中默认项
const selectDefault = (list, isMutiple, item) => {
if (isMutiple) {
// 多选情况下,选中所有项
for (let i = 0; i < list.length; i++) {
list[i].isSelected = true
}
} else {
// 单选情况下,取消选中所有项并清空日期选择框
for (let i = 0; i < list.length; i++) {
list[i].isSelected = false
}
item.dateTime = null
}
item.defaultSelect = true
result[item.key] = ''
emit('resultConditon', result)
} // 多选项点击事件
const selectMutiple = (index, key, isMutiple, item) => {
if (isMutiple) {
// 多选情况下,切换选中状态并更新结果对象
item.detailList[index].isSelected = !item.detailList[index].isSelected
if (!result[key]) {
result[key] = []
}
if (item.detailList[index].isSelected) {
result[key].push(item.detailList[index].value)
} else {
item.detailList[index].isSelected = false
let idx = result[key].indexOf(item.detailList[index].value)
result[key].splice(idx, 1)
}
let length = item.detailList.filter(item => item.isSelected).length
if (length === item.detailList.length || length == 0) {
item.defaultSelect = true
} else {
item.defaultSelect = false
}
console.log(result)
} else {
// 单选情况下,更新选中项并更新结果对象
item.defaultSelect = false
item.dateTime = null
result[key] = item.detailList[index].value
for (let i = 0; i < item.detailList.length; i++) {
if (index == i) {
item.detailList[i].isSelected = true
} else {
item.detailList[i].isSelected = false
}
}
}
emit('resultConditon', result)
} // 选中日期框
const changeDate = (value, key, item) => {
const createTime = value ? [...value].join(',') : ''
result[key] = createTime
item.defaultSelect = false
for (let i = 0; i < item.detailList.length; i++) {
item.detailList[i].isSelected = false
}
if (!createTime) {
item.defaultSelect = true
}
emit('resultConditon', result)
}
</script>
<style lang="scss" scoped>
/* @use ''; 引入css类 */
.fjj-content {
.fjj-list {
row-gap: 10px;
& > li {
.label-box {
margin-right: 8px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #818181;
padding: 8px 0;
}
.tags-list {
li {
padding: 8px 14px;
margin-right: 2px;
cursor: pointer;
span {
line-height: 14px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #333333;
}
&.activeLi {
background: #ebf5ff;
span {
color: #2794ff;
}
}
}
}
}
}
}
</style>

以下是引入代码模块

<template>
<div class="newsInfo">
<!-- 筛选项 -->
<fjj-condition :list="menuList" @resultConditon="resultConditon" />
</div>
</template> <script setup>
/**
* 筛选项数据
*/
const menuList = ref([
{
title: '信源类型',
type: 'custom',
key: 'siteTypes',
isMutiple: true, //多选
defaultLabel: '全选',
defaultSelect: true,
detailList: [
{
value: '6FD6F9F43DE8420',
title: '智库网站'
},
{
value: '5F4990CACF12410',
title: '新闻网站'
},
{
value: '5F4990CACF12666',
title: '社交媒体'
}
]
},
{
title: '采集时间',
type: 'custom',
key: 'createTime',
isMutiple: false, //单选
defaultLabel: '全部',
defaultSelect: true,
childrenType: 'rangetime',
detailList: [
{
title: '24h',
value: 1
},
{
title: '近三日',
value: 2
},
{
title: '最近一周',
value: 3
},
{
title: '最近一个月',
value: 4
}
]
}
])
// 获取筛选项数据
const resultConditon = obj => {
console.log(obj)
}
</script>
<style lang="scss" scoped>
/* @use ''; 引入css类 */
.newsInfo {
padding: 24px 39px 23px 40px;
}
</style>

vue3封装筛选项的更多相关文章

  1. vue3 封装简单的 tabs 切换组件

    背景:公司项目要求全部换成 vue3 ,而且也没有应用像 element-ui 一类的UI组件,用到的公共组件都是根据项目需求封装的,下面是使用vue3实现简单的tabs组件,我只是把代码分享出来,实 ...

  2. vue3 封装el-table时,构造$children(类式写法)

    由于业务需求(组件封装),需要在获取el-table下面的el-table-column实例 在 vue2.x 当中直接使用this.$children就可以获取到该实例 但是 vue3.x 弃用了$ ...

  3. Vue3 封装第三方组件(一)做一个合格的传声筒

    各种UI库的功能都是非常强大的,尤其对于我这种不会 css 的人来说,就更是帮了大忙了. 只是嘛,如果再封装一下的话,那么用起来就会更方便了. 那么如何封装呢? 封装三要素 -- 属性.插槽.事件.方 ...

  4. Vue3 封装 Element Plus Menu 无限级菜单组件

    本文分别使用 SFC(模板方式)和 tsx 方式对 Element Plus el-menu 组件进行二次封装,实现配置化的菜单,有了配置化的菜单,后续便可以根据路由动态渲染菜单. 1 数据结构定义 ...

  5. vue3封装input组件

    使用了2种方法去封装input组件(.vue与.jsx) 代码如下 父组件: <template> <div> <h1>input组件封装</h1> & ...

  6. 【vue3】封装自定义全局插件

    [vue3]封装自定义全局插件 原vue2方法 main.js import Vue from 'vue' import App from './App.vue' import router from ...

  7. [Vue]浅谈Vue3组合式API带来的好处以及选项API的坏处

    前言 如果是经验不够多的同志在学习Vue的时候,在最开始会接触到Vue传统的方式(选项式API),后边会接触到Vue3的新方式 -- 组合式API.相信会有不少同志会陷入迷茫,因为我第一次听到新的名词 ...

  8. 基于element-ui的后台系统表格、dialog、筛选、自定义按钮、分页的一次性封装

    方便基础业务开发封装的一套组件,基于vue2.5.x和element-ui,可以通过配置自动生成表格展示,表格新增.编辑功能.分页.筛选项.自定义显示表格数据等功能. 先上演示图片 --------- ...

  9. Vue3.0+Electron聊天室|electron跨平台仿QQ客户端|vue3.x聊天应用

    基于vue3+electron11跨端仿制QQ桌面应用实战Vue3ElectronQchat. 使用vue3+electron+vuex4+ant-design-vue+v3scroll+v3laye ...

  10. 基于 element-plus 封装一个依赖 json 动态渲染的查询控件

    前情回顾 基于 el-form 封装一个依赖 json 动态渲染的表单控件 Vue3 封装第三方组件(一)做一个合格的传声筒 功能 使用 vue3 + element-plus 封装了一个查询控件,专 ...

随机推荐

  1. 浅谈 OI 中各种合并操作

    前言 合并操作一直是 OI 中一大考点,今天请各位跟着笔者来梳理一下各种合并操作. 启发式合并 几乎可以说是最经典的合并了. 假定我们可以在 \(O(k)\) 的时间内往某个集合中插入一个数,那么我们 ...

  2. WPF入门教程系列二十四——DataGrid使用示例(2)

    WPF入门教程系列目录 WPF入门教程系列二--Application介绍 WPF入门教程系列三--Application介绍(续) WPF入门教程系列四--Dispatcher介绍 WPF入门教程系 ...

  3. 【HarmonyOS】关于 Caused by java.lang.IllegalStateException The specified...

    [问题描述] 线上收到大量手机的崩溃异常,以华为手机为主,崩溃如下 1.Caused by: java.lang.IllegalStateException: The specified messag ...

  4. 20.AQS家族的“外门弟子”:CyclicBarrier

    关注王有志,一个分享硬核Java技术的互金摸鱼侠 欢迎你加入Java人的提桶跑路群:共同富裕的Java人 今天我们来学习AQS家族的"外门弟子":CyclicBarrier. 为什 ...

  5. 稳,从数据库连接池 testOnBorrow 看架构设计

    本文从 Commons DBCP testOnBorrow 的作用机制着手,管中窥豹,从一点去分析数据库连接池获取的过程以及架构分层设计. 以下内容会按照每层的作用,贯穿分析整个调用流程. 1️⃣框架 ...

  6. 如何取消Blazor Server烦人的重新连接?

    如何取消Blazor Server烦人的重新连接? 相信很多Blazor的用户在开发内部系统上基本上都选择速度更快,加载更快的Blazor Server模式. 但是Blazor Server由于是Si ...

  7. C++ 核心指南之资源管理(上)

    C++ 核心指南(C++ Core Guidelines)是由 Bjarne Stroustrup.Herb Sutter 等顶尖 C++ 专家创建的一份 C++ 指南.规则及最佳实践.旨在帮助大家正 ...

  8. 曲线艺术编程 coding curves 第十二章 超级椭圆与超级方程(Superellipses and Superformulas)

    第十三章 超级椭圆与超级方程(Superellipses and Superformulas) 原作:Keith Peters https://www.bit-101.com/blog/2022/11 ...

  9. 自然语言处理 Paddle NLP - 任务式对话系统-理论

    什么是任务型对话: 任务型:用于帮助用户完成某领域的特定任务,例如订餐.查天气.订票等 闲聊型:也称作开放域对话系统,目标是让用户持续的参与到交互过程,提供情感陪伴 问答型:提供知识满足,具体类型比较 ...

  10. gRPC vs. HTTP:网络通信协议的对比

    概述 gRPC 和 HTTP 是两种常见的网络通信协议,用于在客户端和服务器之间进行通信.它们具有不同的特点和适用场景,下面对它们进行详细比较. HTTP(Hypertext Transfer Pro ...