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

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

表单组件

src\components\TableSeach

<template><div class="table-search-root"><el-formref="searchForm"class="table-search__form":model="formData"size="default"label-width="128px"v-bind="formProps"><!-- 查询表单模块 --><el-row class="table-search__row"><el-colv-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><componentv-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-optionv-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><spanv-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><TableSeachv-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.hqwc.cn/news/640882.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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;文档与支持&#…

ScriptableObject数据容器讲解

概述 是Unity提供的一个用于创建可重用的数据容器或逻辑的基类。 ScriptableObject 是继承自 UnityEngine.Object 的一个类&#xff0c;但与普通的 MonoBehaviour 不同&#xff0c;它不能附加到GameObject上作为组件。 相反&#xff0c;ScriptableObject 通常用于存储和管理…

【JavaSE启航篇 01】探索JavaSE:史上最强JavaSE学习路线图 知识图谱

【JavaSE启航篇 01】探索JavaSE&#xff1a;史上最强JavaSE学习路线图 &知识图谱 作者名称&#xff1a;纸飞机-暖阳 作者简介&#xff1a;专注于Java和大数据领域&#xff0c;致力于探索技术的边界&#xff0c;分享前沿的实践和洞见 文章专栏&#xff1a;JavaSE那些年专栏 …

数据库管理-第173期 OceanBase一体化Plus多模融合(20240422)

数据库管理173期 2024-04-22 数据库管理-第173期 OceanBase一体化Plus多模融合&#xff08;20240422&#xff09;1 架构简化2 不止融合2.1 行列混存2.2 多维使用2.3 多模JOIN 3 展望 数据库管理-第173期 OceanBase一体化Plus多模融合&#xff08;20240422&#xff09; 作者&…

3D Gaussian Splatting介绍

目录 一、概述二、基础介绍1. 多维高斯分布2. 将3D 高斯投影到2D像素平面3. 球谐函数4. Splatting and α \alpha α blending 三、整体流程四、 伪代码五、评价指标六、实验结果七、reference 一、概述 3D Gaussian Splatting和NeRF一样&#xff0c;主要用于新视图合成。 特…

eCharts 折线图 一段是实线,一段是虚线的实现效果

在lineStyle里写了不生效的话&#xff0c;可以尝试数据拼接 option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [150, 230, 224,218 ,,,],type: line},{data: [,,, 218, 135, 147, 260],type: line,lineStyl…

Valentina Studio Pro for Mac:强大的数据库管理工具

Valentina Studio Pro for Mac是一款功能全面、操作高效的数据库管理工具&#xff0c;专为Mac用户设计&#xff0c;旨在帮助用户轻松管理各种类型的数据库。 Valentina Studio Pro for Mac v13.10激活版下载 该软件拥有直观的用户界面&#xff0c;使得数据库管理变得简单直观。…

ChromaDB教程

使用 Chroma DB&#xff0c;管理文本文档、将文本嵌入以及进行相似度搜索。 随着大型语言模型 &#xff08;LLM&#xff09; 及其应用的兴起&#xff0c;我们看到向量数据库越来越受欢迎。这是因为使用 LLM 需要一种与传统机器学习模型不同的方法。 LLM 的核心支持技术之一是…

CSS-vminvmax单位

vmin 和 vmax 单位 vmin 是相对于视口宽度和高度中较小值进行计算&#xff0c;它的值为视口宽度和高度中的较小值的百分比。 例如&#xff0c;如果视口宽度为 800px&#xff0c;高度为 1000px&#xff0c;那么 1vmin 等于 8px&#xff08;800px 的 1%&#xff09;。 vmax 是…

半年来每月必用,隐私协议Railgun因何得到Vitalik的青睐?

还没有哪个隐私协议能让 Vitalik 每个月都转入以太坊交互&#xff0c;但 Railgun 做到了。在过去 6 个月中&#xff0c;Vitalik 基本每个月都会使用 ETH 与 Railgun 交互&#xff0c;随后被 Vitalik 推特确认&#xff0c;并为 Railgun 打了个小广告。市场反应迅速&#xff0c;其…

书生·浦语大模型实战训练营--第二期第七节--OpenCompass大模型评测实战--homework

一、配置环境 安装下面的顺序以及自己的文件路径配置环境 conda create -n opencompass python3.10 -y 安装下面的包 absl-py accelerate>0.19.0 boto3 cn2an cpm_kernels datasets>2.12.0 einops0.5.0 evaluate>0.3.0 fairscale func_timeout fuzzywuzzy immutab…

mininet+odl安装

安装环境 ubuntu-18.04.2-desktop-amd64 Java version: 1.8.0_362 Apache Maven 3.6.0 opendaylight: distribution-karaf-0.6.0-Carbon(csdn中应该是已有资源&#xff0c;不让上传) opendaylight的官网下载链接一直打开失败&#xff0c;我使用的是别人的Carbon版本。 在安…