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

news2024/11/16 13:37:47

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉 CV 八股分享 [自用](更新中......)

目录 一、深度学习中解决过拟合方法 二、深度学习中解决欠拟合方法 三、梯度消失和梯度爆炸 解决梯度消失的方法 解决梯度爆炸的方法 四、神经网络权重初始化方法 五、梯度下降法 六、BatchNorm 七、归一化方法 八、卷积 九、池化 十、激活函数 十一、预训练 十二…

[Kotlin]引导页

使用Kotlin Jetpack Compose创建一个左右滑动的引导页, 效果如图. 1.添加依赖项 androidx.compose.ui最新版本查询:https://maven.google.com/web/index.html com.google.accompanist:accompanist-pager最新版本查询:https://central.sonatype.com/ 确保在 build.gradle (M…

海康Visionmaster-常见问题排查方法-安装阶段

VM软加密安装失败&#xff0c;报错&#xff1a;软件未激活&#xff0c;是否进行授权激活&#xff1b; 解决方法&#xff1a;如确认已完成授权&#xff0c;此时打上试用用补丁即可。补充VM400试用版本正确安装顺序如下&#xff1a; 安装顺序&#xff1a; ①安装基础安装包&…

14.接口自动化测试-造数据

1.测试造数据 工作场景&#xff1a; 需要造一批测试数据 解决方案&#xff1a; &#xff08;1&#xff09;使用字符串拼接 135XXXXX &#xff08;2&#xff09;使用第三方库去做 faker 安装&#xff1a; pip install Faker 若安装不成功&#xff0c;可能是需要清下缓存&a…

ChatGPT在线网页版(与GPT Plus会员完全一致)

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

Linux及tmux、vim常用命令

Linux 关于Linux的简介、诞生、迭代&#xff0c;大家可以去网上查一查&#xff0c;这里不多做赘述了 Linux文件类型 非常重要的文件类型有: 普通文件&#xff0c;目录文件&#xff0c;链接文件&#xff0c;设备文件&#xff0c;管道文件&#xff0c;Socket 套接字文件 等。 …

SLICEM是如何将查找表配置为分布式RAM/移位寄存器的

1.首先说SliceM和SliceL如何配置为ROM的 一个SLICE包含4个六输入查找表&#xff0c;因此每个查找表就能存储64bit的数据&#xff0c;要实现128bit的ROM&#xff0c;只需要通过两个LUT就可实现&#xff0c;具体如下表: 2.如何配置成为分布式RAM SLICEM中的LUT如下图&#xff…

macbook内存怎么清理?2024年有哪些好用的软件

当你的MacBook运行缓慢时&#xff0c;这很可能是因为内存&#xff08;RAM&#xff09;满了。内存是计算机的临时存储区&#xff0c;用于存放当前正在使用的程序和数据。当内存满时&#xff0c;MacBook就会使用硬盘作为临时内存&#xff0c;这大大降低了运行速度。那么&#xff…

ffmpeg初体验

一&#xff1a;安装 sudo yum install epel-release -y sudo yum update -ysudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpmyum -y install …

docker-MySQL 8 主从搭建

一.目录结构&#xff1a; 我是在/home目录下&#xff0c;建立个sql文件夹&#xff1a; 二、配置文件 1.mysql配置 mysql-master下.conf文件配置 ###### [mysqld] server-id1 # 启用二进制日志 log-binmaster-bin # 指定需要复制的数据库 binlog-do-dbtest_db # 指定二进制日…

《动手学深度学习(Pytorch版)》Task01:初识深度学习——4.22打卡

深度学习介绍 AI地图 自然语言处理&#xff1a;起源于符号学&#xff0c;如机器翻译&#xff0c;人在几秒钟能反应过来&#xff0c;属于感知问题计算机视觉&#xff1a;图片由像素组成&#xff0c;难以用符号学解释&#xff0c;在图片中进行推理&#xff0c;大部分用概率模型或…

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

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

若依集成mybatisplus报错找不到xml

引用&#xff1a;https://blog.csdn.net/qq_65080131/article/details/136677276 MybatisPlusAutoConfiguration中可以知道&#xff0c;系统会自动配置SqlSessionFactory&#xff0c;&#xff0c;但是&#xff0c;当你有自定义的SqlSessionFactory&#xff0c;&#xff0c;就会…

如何使用rdtsc和C/C++来测量运行时间(如何使用内联汇编和获取CPU的TSC时钟频率)

本文主要是一个实验和思维扩展&#xff0c;除非你有特殊用途&#xff0c;不然不要使用汇编指令来实现这个功能。扩展阅读就列出了一些不需要内联汇编实现的 写本文是因为为了《Windows上的类似clock_gettime(CLOCK_MONOTONIC)的高精度测量时间函数》这篇文章找资料的时候&…

arm架构,django4.2.7适配达梦8数据库

【Python相关包版本信息】 Django 4.2.7 django-dmPython 3.1.7 dmPython 2.5.5 【达梦数据库版本】 DM Database Server 64 V8 DB Version: 0x7000c 适配过程中发现的问题如下&#xff1a; 错误一&#xff1a;d…

Opencv | 图像卷积与形态学变换操作

这里写目录标题 一. 滤波 / 卷积操作1. 平滑均值滤波/卷积2. 平滑中值滤波/卷积3. 平滑高斯滤波/卷积3.1 关注区域3.2 分解特性 二. 形态学变换1. 常用核2. cv.erode ( ) 腐蚀操作3. cv.dilate ( ) 膨胀操作4. Open 操作5. Close 操作6. Morphological Gradient 形态梯度操作7.…

为什么单片机控制电机需要加电机驱动

通常很多地方只是单纯的单片机MCU没有对电机的驱动能力&#xff0c;或者是介绍关于电机驱动的作用&#xff0c;如&#xff1a; 提高电机的效率和精度。驱动器采用先进的电子技术和控制算法&#xff0c;能够精准控制电机的参数和运行状态&#xff0c;提高了电机的效率和精度。拓…

vos3000外呼系统客户端无法安装如何解决?

如果 VOS3000 外呼系统客户端无法安装&#xff0c;可以尝试以下解决方法&#xff1a; 检查系统要求&#xff1a; 确保你的计算机满足 VOS3000 外呼系统客户端的系统要求&#xff0c;包括操作系统版本、内存、处理器等。如果系统不符合要求&#xff0c;可能会导致安装失败或者运…

[BT]BUUCTF刷题第20天(4.22)

第20天 Web [GWCTF 2019]我有一个数据库 打开网站发现乱码信息&#xff08;查看其他题解发现显示的是&#xff1a;我有一个数据库&#xff0c;但里面什么也没有~ 不信你找&#xff09; 但也不是明显信息&#xff0c;通过dirsearch扫描得到robots.txt&#xff0c;然后在里面得…

echarts 双堆叠柱状图(数据整理)

1.后台返回的数据格式 {"code": "0000","message": "","messageCode": "操作成功","sign": null,"detail": null,"data": {"pieChart": [{"key": "产品…