vue3组件封装系列-表单请求

我们在开发一些后台管理系统时,总是会写很多的列表查询页面,如果不封装组件,就会无限的复制粘贴,而且页面很冗余,正常情况下,我们都是要把组件进行二次封装,来达到我们想要效果。这里我分享一下我近期封装的关于列表的组件封装。
vue3+element-plus

表单组件

src\components\TableSeach

<template>
    <div class="table-search-root">
        <el-form
            ref="searchForm"
            class="table-search__form"
            :model="formData"
            size="default"
            label-width="128px"
            v-bind="formProps"
        >
            <!-- 查询表单模块 -->
            <el-row class="table-search__row">
                <el-col
                    v-for="(field, index) in fields"
                    :key="field.prop"
                    class="table-search__col"
                    :class="{ 'form__item--hidden': shouldCollapse(index) }"
                    :xl="6"
                    :lg="8"
                    :md="12"
                    :sm="24"
                >
                    <el-form-item :label="field.label" :prop="field.prop">
                        <slot v-if="$slots[field.prop]" :name="field.prop"></slot>

                        <component
                            v-else
                            :is="field.type"
                            v-model.trim="formData[field.prop]"
                            :placeholder="defaultPlaceHolder(field)"
                            v-bind="getFormFieldProps(field.type, field.props)"
                        >
                            <template v-if="field.type === FieldsType.SELECT">
                                <el-option
                                    v-for="option in field.options"
                                    :key="option.value"
                                    :label="option.label"
                                    :value="option.value"
                                />
                            </template>
                        </component>
                    </el-form-item>
                </el-col>

                <!-- 操作按钮模块 -->
                <div class="table-search__btns">
                    <el-button type="primary" :loading="props.loading" @click="handleSearch">
                        查询
                    </el-button>
                    <el-button :loading="props.loading" @click="handleReset"> 重置 </el-button>
                    <span
                        v-if="showCollapseBtn"
                        class="table-search__btn--filter ml-28"
                        @click="toggleCollapse"
                    >
                        {{ isCollapse ? '展开' : '收起' }}
                        <el-icon color="#c0c4cc" v-show="isCollapse"><CaretBottom /></el-icon>
                        <el-icon color="#c0c4cc" v-show="!isCollapse"><CaretTop /></el-icon>
                    </span>
                </div>
            </el-row>
        </el-form>
    </div>
</template>
<script lang="ts">
// 解决组件不渲染问题---使用的是自动引入方式,不知为何有bug,暂时只能用这种方式解决,有好办法的也可以分享一下 
import {
    ElInput,
    ElInputNumber,
    ElSelect,
    ElTimePicker,
    ElTimeSelect,
    ElDatePicker
} from 'element-plus';
export default {
    components: {
        ElInput,
        ElInputNumber,
        ElSelect,
        ElTimePicker,
        ElDatePicker,
        ElTimeSelect
    }
};
</script>
<script setup lang="ts">
import { type PropType, ref, toRefs, computed } from 'vue';
import defaultFieldsProps from './defaultFieldsProps';
const FieldsType = {
    INPUT: 'el-input',
    SELECT: 'el-select'
};
type filed = {
    prop: string;
    label?: string;
    type?: string;
    options?: any[];
    [propName: string]: any;
};
interface size {
    width: number;
    quantity: number;
}
// 不同尺寸所对应的页面宽度和每行 ElFormItem 个数
const DifferentSizeData = [
    { width: 1900, quantity: 4 }, // xl
    { width: 1200, quantity: 3 }, // large
    { width: 992, quantity: 2 }, // middle
    { width: 768, quantity: 1 }, // small
    { width: 0, quantity: 1 } // less than small
];
const props = defineProps({
    modelValue: {
        type: Object,
        default: () => ({})
    },
    formProps: {
        type: Object,
        default: () => ({})
    },
    fields: {
        type: Array as PropType<filed[]>,
        default: () => []
    },
    defaultCollapse: {
        type: Boolean,
        default: false
    },
    loading: {
        type: Boolean,
        default: false
    }
});
const formData: { [key: string]: any } = defineModel();
const emit = defineEmits(['search', 'reset']);
const { defaultCollapse, fields, formProps } = toRefs(props);
const isCollapse = ref(true);
isCollapse.value = defaultCollapse.value;
const searchForm = ref<any>(null);
const showCollapseBtn = computed(() => {
    const quantity = getPerLineItemQuantity();
    return fields.value.length >= quantity;
});
const getFormFieldProps = (fieldType: any, props: any) => {
    const defaultProps: { [key: string]: any } = defaultFieldsProps;
    return { ...defaultProps[fieldType], ...props };
};
const shouldCollapse = (index: any) => {
    const quantity = getPerLineItemQuantity();
    return index > quantity - 2 && isCollapse.value;
};
const getPerLineItemQuantity = () => {
    const documentScrollWidth = document.documentElement.scrollWidth;
    const size = DifferentSizeData.find((item) => documentScrollWidth >= item.width);

    return (size as size).quantity;
};
const defaultPlaceHolder = (field: any) => {
    const newLabel = field.label.replace(':', '').replace(':', '');
    return field.type === FieldsType.SELECT ? `请选择${newLabel}` : `请输入${newLabel}`;
};
const toggleCollapse = () => {
    isCollapse.value = !isCollapse.value;
};
const handleSearch = () => {
    emit('search', formData.value);
};
const handleReset = () => {
    searchForm.value.resetFields();
    emit('reset', formData.value);
};
const handleResetForm = () => {
    searchForm.value.resetFields();
};
defineExpose({
    handleResetForm
});
</script>
<style lang="scss" scoped>
/**  查询表单模块样式  **/
.table-search__form {
    display: flex;
    flex-wrap: wrap;
}

.table-search__row {
    width: 100%;
}

.table-search__col:last-of-type {
    margin-bottom: 0;
}

:deep(.el-form-item__label) {
    width: 128px;
    white-space: nowrap;
    overflow: hidden;
    font-weight: 400;
    font-size: 14px;
    color: #282828;
}

:deep(.el-select),
:deep(.el-cascader),
:deep(.el-date-editor--daterange.el-input),
:deep(.el-date-editor--daterange.el-input__inner),
:deep(.el-date-editor--timerange.el-input),
:deep(.el-date-editor--timerange.el-input__inner),
:deep(.el-date-editor--datetimerange.el-input),
:deep(.el-date-editor--datetimerange.el-input__inner) {
    width: 100%;
}

:deep(.el-date-editor .el-range-separator) {
    width: auto;
}

.form__item--hidden {
    display: none;
}

/**  操作按钮模块样式  **/
.table-search__btns {
    margin-left: auto;
    margin-bottom: 16px;
}

.table-search__btn--filter {
    font-size: 14px;
    color: #606266;
    cursor: pointer;
}

/**  功能样式  **/
.ml-28 {
    margin-left: 28px;
}
</style>

src\components\TableSeach\defaultFieldsProps.ts

export default {
  'date-picker': {
    valueFormat: 'x',
  },
  XXXXX这里写一些项目公共的想要特殊处理的参数
};

表单组件就是这样

使用效果

收起状态
在这里插入图片描述

展开状态
在这里插入图片描述

使用方式

<template>
    <TableSeach
      v-model="searchQuery"
      ref="TableSeach"
      :fields="serchFields"
      :formProps="{
          labelWidth: '120px'
      }"
      :loading="loading.tableLoading"
      @search="handleQuery"
      @reset="handleQuery"
   >
      <template #staff_ids>
          基础组件无法实现的情况下可以用插槽的方式添加其他组件用以实现
      </template>
      <template #tags>
           基础组件无法实现的情况下可以用插槽的方式添加其他组件用以实现
      </template>
  </TableSeach>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import TableSeach from '@/components/TableSeach/index.vue';

const searchQuery = ref({
    xxxxxxx:xxxxx
});
const loading = ref({
    tableLoading: false
});

onMounted(() => {
    handleQuery();
});
const handleQuery = async () => {
    xxxxxxxxxxx
};

const serchFields = [
    {
            label: 'xxxxxx',
            prop: 'time',
            type: FormType.DATE_PICKER,
            props: {
                type: 'daterange',
                startPlaceholder: '开始日期',
                endPlaceholder: '结束日期',
                disabledDate: disabledDate, 
                valueFormat: YMD
            }
        },
        {
            label: 'xxxxxxx',
            prop: 'staff_ids'
        },
        {
            label: 'xxxxx',
            prop: 'tags'
        },
        {
            label: 'xxxxxx',
            prop: 'loss',
            type: FormType.SELECT,
            options: [{ value: -1, label: '全部' }, ...dynamicList]
        },
        {
            label: 'xxxxxx',
            prop: 'del_staff_id',
            type: FormType.SELECT,
            options: staffOptions.value,
            props: {
                filterable: true,
                remote: true,
                loading: loading.value.staffLoading,
                remoteMethod: remoteStaffMethod
            }
        },
        xxxxxxxxxxxxxxxx
]
</script>

如上,除了部分参数key是需要固定以外,其余element本身自带的参数也全部可以使用props传入,特殊需求在组件不满足情况下也可以使用插槽形式更改显示

本示例只是简单写了一下,在某些情况下需要传入参数也可以将serchFields改为function接收参数

有什么问题的欢迎提出,也欢迎大佬指出不足之处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/565868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

centos执行mpd遇到bash:mpd:command not found错误

错误原因 我用的版本是centos7及mpich-3.2。在搭建mpi并行计算时&#xff0c;按照很多教程说的使用mpd&#xff0c;但是遇到了bash&#xff1a;mpd&#xff1a;command not found错误&#xff08;见下图&#xff09;&#xff0c;我尝试着去装mpd&#xff0c;未果&#xff1b;也…

深度学习500问——Chapter08:目标检测(3)

文章目录 8.2.7 DetNet 8.2.8 CBNet 8.2.7 DetNet DetNet是发表在ECCV2018的论文&#xff0c;出发点是现有的检测任务backbone都是从分类任务衍生而来的&#xff0c;因此作者想针对检测专用的backbone做一些讨论和研究而设计了DetNet&#xff0c;思路比较新奇。 1. Introduct…

Linux查看僵尸进程

1、查看系统是否有僵尸进程 使用Top命令查找&#xff0c;当zombie前的数量不为0时&#xff0c;即系统内存在相应数量的僵尸进程。 2、定位僵尸进程 使用命令ps -A -ostat,ppid,pid,cmd |grep -e ‘^[Zz]’定位僵尸进程以及该僵尸进程的父进程。 3、杀死僵尸进程 使用Kill -…

【NLP练习】使用Word2Vec实现文本分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、数据预处理 1. 任务说明 本次加入Word2Vec使用PyTorch实现中文文本分类&#xff0c;Word2Vec则是其中的一种词嵌入方法&#xff0c;是一种用于生成词向量…

【多态】底层原理

博主首页&#xff1a; 有趣的中国人 专栏首页&#xff1a; C进阶 本篇文章主要讲解 多态底层原理 的相关内容 1. 多态原理 1.1 虚函数表 先看一下这段代码&#xff0c;计算一下sizeof(Base)是多少&#xff1a; class Base { public:virtual void Func1(){cout << &quo…

力扣--N皇后

题目: 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。…

Android驱动开发之如何编译和更换内核

编译内核可以使用图形化的界面配置,也可以直接使用脚本。在X86_64模拟器环境下,不用交叉编译,而交叉编译工具很容易出现兼容问题,一般也只能使用芯片厂商提供的工具,而不是GNU提供的工具。 android内核开发流程以及架构变化了很多,详情请看 内核官网 内核版本选择 由…

蓝桥杯第17169题——兽之泪II

问题描述 在蓝桥王国&#xff0c;流传着一个古老的传说&#xff1a;在怪兽谷&#xff0c;有一笔由神圣骑士留下的宝藏。 小蓝是一位年轻而勇敢的冒险家&#xff0c;他决定去寻找宝藏。根据远古卷轴的提示&#xff0c;如果要找到宝藏&#xff0c;那么需要集齐 n 滴兽之泪&#…

NFTScan | 04.15~04.21 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期&#xff1a;2024.04.15~ 2024.04.21 NFT Hot News 01/ 数据&#xff1a;Bitcoin Puppets 市值超越 Pudgy Penguins&#xff0c;现排名第五 4 月 15 日&#xff0c;据 CoinGecko 数据显示&#xff0c…

LeetCode in Python 72. Edit Distance (编辑距离)

编辑距离的基本思想很直观&#xff0c;即不断比较两个单词每个位置的元素&#xff0c;若相同则比较下一个&#xff0c;若不同则需要考虑从插入、删除、替换三种方法中选择一个最优的策略。涉及最优策略笔者最先想到的即是动态规划的思想&#xff0c;将两个单词的位置对应放在矩…

zigbee cc2530的室内/矿井等定位系统RSSI原理

1. 定位节点软件设计流程 2. 硬件设计 cc2530 最小系统 3. 上位机 c# 设计上位机&#xff0c;通过串口连接协调器节点&#xff0c;传输数据到pc上位机&#xff0c;显示节点坐标信息 4. 实物效果 需要4个节点&#xff0c;其中一个协调器&#xff0c;两个路由器作为参考节点&a…

计算机视觉 | 交通信号灯状态的检测和识别

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目旨在使用计算机视觉技术检测交通信号灯的状态&#xff0c;主要针对红色和绿色信号灯的识别。通过分析输入图像中的像素颜色信息&#xff0c;利用OpenCV库实现对信号灯状态的检测和识别。 目录 一、项目背景 二、项目功能…

uni-app 的 扩展组件(uni-ui) 与uView UI

uni-app 的 扩展组件&#xff08;uni-ui&#xff09; 与uView UI uni-ui 官方背景&#xff1a;组件集&#xff1a;设计风格&#xff1a;文档与支持&#xff1a;社区与生态&#xff1a; uView UI 第三方框架&#xff1a;组件集&#xff1a;设计风格&#xff1a;文档与支持&#…

Python --- 新手小白自己动手安装Anaconda+Jupyter Notebook全记录(Windows平台)

新手小白自己动手安装AnacondaJupyter Notebook全记录 这两天在家学Pythonmathine learning&#xff0c;在我刚刚入手python的时候&#xff0c;我写了一篇新手的入手文章&#xff0c;是基于Vs code编译器的入手指南&#xff0c;里面包括如何安装python&#xff0c;以及如何在Vs…

四六级英语听力考试音频无线发射系统在安顺学院的成功应用分析

四六级英语听力考试音频无线发射系统在安顺学院的成功应用分析 由北京海特伟业科技任洪卓发布于2024年4月22日 安顺学院为了提高学生的外语听力水平&#xff0c;并确保英语四六级听力考试的稳定可靠进行&#xff0c;决定对传统的英语听力音频传输系统进行改造&#xff0c;以提供…

海康Visionmaster-常见问题排查方法-启动阶段

VM试用版启动时&#xff0c;弹窗报错&#xff1a;加密狗未安装或检测异常&#xff1b;  问题原因&#xff1a;安装VM 的时候未选择软加密&#xff0c;选择了加密狗驱动&#xff0c;此时要使用软授权就出现了此现象。  解决方法&#xff1a; ① 首先确认软加密驱动正确安装…

单片机 VS 嵌入式LInux (学习方法)

linux 嵌入式开发岗位需要掌握Linux的主要原因之一是&#xff0c;许多嵌入式系统正在向更复杂、更功能丰富的方向发展&#xff0c;需要更强大的操作系统支持。而Linux作为开源、稳定且灵活的操作系统&#xff0c;已经成为许多嵌入式系统的首选。以下是为什么嵌入式开发岗位通常…

机器学习-10-神经网络python实现-从零开始

文章目录 总结参考本门课程的目标机器学习定义从零构建神经网络手写数据集MNIST介绍代码读取数据集MNIST神经网络实现测试手写的图片 带有反向查询的神经网络实现 总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍基于python实现神经网络。 参考 BP神经网络及pytho…

数据挖掘实验(Apriori,fpgrowth)

Apriori&#xff1a;这里做了个小优化&#xff0c;比如abcde和adcef自连接出的新项集abcdef&#xff0c;可以用abcde的位置和f的位置取交集&#xff0c;这样第n项集的计算可以用n-1项集的信息和数字本身的位置信息计算出来&#xff0c;只需要保存第n-1项集的位置信息就可以提速…

去哪儿网开源的一个对应用透明,无侵入的Java应用诊断工具

今天 V 哥给大家带来一款开源工具Bistoury&#xff0c;Bistoury 是去哪儿网开源的一个对应用透明&#xff0c;无侵入的java应用诊断工具&#xff0c;用于提升开发人员的诊断效率和能力。 Bistoury 的目标是一站式java应用诊断解决方案&#xff0c;让开发人员无需登录机器或修改…