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

这篇具有很好参考价值的文章主要介绍了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这里写一些项目公共的想要特殊处理的参数
};

表单组件就是这样

使用效果

收起状态
vue3组件封装系列-表单请求,vue.js,前端

展开状态
vue3组件封装系列-表单请求,vue.js,前端

使用方式

<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接收参数

有什么问题的欢迎提出,也欢迎大佬指出不足之处文章来源地址https://www.toymoban.com/news/detail-856154.html

到了这里,关于vue3组件封装系列-表单请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3中搜索表单的二次封装

    最近使用Vue3+ElementPlus开发项目,从整体上构思组件的封装。能写成组件的内容都进行封装,方便多个地方使用。 受AntDesign的启发,在项目中有搜索表单+table+分页的地方可以封装为一个组件,只需要对组件传入table的列,组成一个配置项,通过配置可以显示搜索表单、table项的

    2024年02月11日
    浏览(30)
  • vue3,elementPlus和自己封装,点击 新增添加表单,删除表单,提交数据

    点击提交的打印效果 components/insertForm.vue 主文件引入 效果一样 *

    2024年02月16日
    浏览(28)
  • 【尚医通】vue3+ts前端项目开发笔记 2 —— 创建项目、封装网络请求、集成elment-plus 、重置样式、准备状态管理/路由 等开发前准备

    服务器地址:http://syt.atguigu.cn 医院接口:http://139.198.34.216:8201/swagger-ui.html 公共数据接口:http://139.198.34.216:8202/swagger-ui.html 会员接口:http://139.198.34.216:8203/swagger-ui.html 短信验证码接口:http://139.198.34.216:8204/swagger-ui.html 订单接口:http://139.198.34.216:8206/swagger-ui.html 文件上传接口:

    2024年02月13日
    浏览(38)
  • Vue-Element-Admin项目学习笔记(9)表单组件封装,父子组件双向通信

    前情回顾: vue-element-admin项目学习笔记(1)安装、配置、启动项目 vue-element-admin项目学习笔记(2)main.js 文件分析 vue-element-admin项目学习笔记(3)路由分析一:静态路由 vue-element-admin项目学习笔记(4)路由分析二:动态路由及permission.js vue-element-admin项目学习笔记(5)路由分析

    2024年02月11日
    浏览(39)
  • Vue3+Axios网络请求封装

    本文将详细介绍一款基于Axios+Typescript封装的网络请求库,该库可以自动携带token、拦截请求和响应等操作,并能够处理请求重复、超时和错误状态码等异常情况。 Axios 是基于Node.js的HTTP客户端,也是一款广泛使用的网络请求库。它具有使用简单、可扩展性高、易用性好等特点

    2024年02月07日
    浏览(29)
  • 用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能。

    Vue3 的父子组件传值、绑定表单数据、UI库的二次封装、防抖等,想来大家都很熟悉了,本篇介绍一种使用 Typescript 的方式进行统一的封装的方法。 Vue3对于表单的绑定提供了一种简单的方式: v-model 。对于使用者来说非常方便, v- model=\\\"name\\\" 就可以了。 但是当我们要自己做一

    2024年02月06日
    浏览(31)
  • Vue3的axios请求封装,请求拦截,相应拦截

    对于三者放在Service.js中封装,方便使用 axios.create  的作用是创建一个新的  axios  实例,该实例可以具有自定义配置。通过使用  axios.create ,您可以为任何 API 生成一个客户端,并在使用同一客户端的任何调用中重复使用相同的配置。这使得在应用程序中使用多个 API 时更加

    2024年02月03日
    浏览(26)
  • Vue组件封装:基于Vue3+wangeditor富文本组件二次封装

    1.简介         开源 Web 富文本编辑器,开箱即用,配置简单。一个产品的价值,就在于解决用户的问题,提高效率、降低成本、增加稳定性和扩展性。wangEditor 不是为了做而做,也不是单纯的模仿谁,而是经过上述问题分析之后,给出一个系统的解决方案。旨在真正去解决用

    2024年04月08日
    浏览(30)
  • 【前端】vue3 接入antdv表单校验

    1、表单校验是非常常见的需求,能够有效的拦截大部分的错误数据,提升效率。 2、快速的给使用者提示和反馈,用户体验感非常好。 3、成熟的表单校验框架,开发效率高,bug少。 最近使用的是vue3+antdv的架子,仔细探究一下表单校验的问题,总结一下。 框架可能不同,主

    2024年02月11日
    浏览(35)
  • vue3范围选择组件封装

    个人项目地址: SubTopH前端开发个人站 (自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面) SubTopH前端开发个人站 https://subtop.gitee.io/subtoph.github.io/#/home 实现效果 直接上代码 组件文件  组件使用

    2024年02月11日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包