vue3封装搜索表单组件

简介: vue3封装搜索表单组件

seacrch 表单完成的功能

1.根据配置json配置项自动生成表单 ok
2.是响应式的排版 ok
3.点击搜索按钮会向上抛出值 ok
4.点击重置按钮会自动清空数据,不需要父组件额外的处理 ok
5.调整按钮靠右,使用flex的填充属性 ok
6.给下拉框绑定了事件 ok
7.新增了插槽,增强组件的扩展性 ok 
8.可以回填默认值  ok
9.下拉框终于可以正确显示placeholder ok
10.可以获取初始值,通过开发者自己手动进行配置就可以了?

处理的小问题

#### 1.在屏幕变小的情况下:日期选择器组件与其他组件宽度不能够保持一致.
解决办法是给一个类,宽度设置为100%
<a-date-picker class="setdate-width"></a-date-picker>
<a-range-picker class="setdate-width"></a-range-picker>
.setdate-width{
    width: 100%;
}
#### 2.按钮始终在最右边。
解决办法是给col 支持flex的填充功能。
当flex="auto"的时候回自动填充剩下的区域
然后靠右就可以按钮始终在最右边。
<a-col flex="auto" class="btnflex"></a-col>
.btnflex{
    text-align: right;
    padding-right: 50px !important;
}
#### 3.设置表单label的宽度
解决办法:<a-form>组件有一个label-col属性。
这个属性接受一个对象通过设置宽度就可以了。
<a-form :model="formState" :label-col="labelCol" :wrapper-col="wrapperCol">
</a-form>
let  labelCol={ style: { width: '150px' } }
这样label的宽度就是150px了

封装组件的思想

1.父组件传递过来的数据,只作为渲染的结构
2.子组件中的v-model的数据是通过父组件传递过来的值进行过滤。
  变成我们想要的数据结构。v-model的数据是子组件内部自己提供的
  这样我们就可以在子组件中做很多的事情。比如清除值。
  如果使用外部的数据,子组件无法更改外部数据。起不到作用

搜索表单的子组件

<template>
    <a-form :model="formDataViewShow" class="search-cont" :label-col="labelCol">
        <a-row class="box" :gutter="40">
            <a-col :xxl="{ span: 6 }" :xl="{ span: 6 }" :lg="{ span: 12 }" :md="{ span: 12 }" :sm="{ span: 24 }"
                :xs="{ span: 24 }" v-for="(item, index) in listForm" :key="index">
                <!-- 自定义插槽 -->
                <template v-if="item.slotName">
                    <slot :name="item.keyName" :row="formDataViewShow"></slot>
                </template>
                <a-form-item :label="item.label || ''" v-if="item.type === 'a-input'">
                    <a-input v-model:value="formDataViewShow[item.keyName]"
                     :placeholder="item.placeholder || '请输入'" />
                </a-form-item>
                <!-- 下拉框 -->
                <a-form-item :label="item.label || ''" v-if="item.type === 'a-select'">
                    <a-select v-model:value="formDataViewShow[item.keyName]" 
                    :placeholder="item.placeholder || '请输入'"
                        @change="changeHandler">
                        <a-select-option :value="selectCont.value" 
                        v-for="(selectCont, selectIndex) in item.options"
                            :key="selectIndex">
                            {{ selectCont.label }}
                        </a-select-option>
                    </a-select>
                </a-form-item>
                <!-- 日期选择器
                 valueFormat="YYYY-MM-DD" 表示得到年月日
                  format="YYYY-MM-DD" 数据展示年月日
                -->
                <a-form-item :label="item.label || ''" v-if="item.type === 'a-date-picker'">
                    <a-date-picker v-model:value="formDataViewShow[item.keyName]" valueFormat="YYYY-MM-DD"
                        format="YYYY-MM-DD" class="setdate-width" />
                </a-form-item>
                <!-- 时间段 -->
                <a-form-item :label="item.label || ''" v-if="item.type === 'a-range-picker'">
                    <a-range-picker v-model:value="formDataViewShow[item.keyName]" valueFormat="YYYY-MM-DD"
                        format="YYYY-MM-DD" class="setdate-width" />
                </a-form-item>
                <!-- 数字输入框 -->
                <a-form-item :label="item.label || ''" v-if="item.type === 'a-input-number'">
                    <a-input-number id="inputNumber" v-model:value="value" :min="1" :max="10" />
                </a-form-item>
            </a-col>
            <a-col flex="auto" class="btnflex">
                <!-- <a-form-item> -->
                <a-button type="primary" @click="searchHandler">搜索</a-button>
                <a-button style="margin-left: 10px" @click="resetHandler">重置</a-button>
                <!-- </a-form-item> -->
            </a-col>
        </a-row>
    </a-form>
</template>
<script lang="ts" setup >
import { defineProps, defineEmits, ref } from 'vue'
const props = defineProps({
    listForm: {
        type: Array,
        required: true,
        default: () => []
    },
})
const emit = defineEmits(['resetHandler', 'searchHandler'])
// 获取视图上需要展示的格式,
// 如果是下拉框的话,没有值需要处理成为undefined
// 该方法是在 1.视图初始化的时候 2.重置表单的时候调用
const getFormData = () => {
    const result: any = {}
    props.listForm.map(item => {
        // item.default  可以直接去解决下拉框没有值,显示不出来placeholder
        if (item.type == 'a-select') {
            result[item.keyName] = item.default || undefined
        } else { 
            result[item.keyName] = item.default || ''
        }
    })
    return result
}
// 给视图
const formDataViewShow = ref(getFormData())
// 重置表单清除视图上的数据,需要注意点是 下拉框的值应为undefined
const clearDealBack = () => { 
    // 清除视图上的值
    formDataViewShow.value = getFormData()
    // 将视图上的数据恢复最初, 下拉框仍然是undefined
    let obj = getFormData() 
    //如果返回去的数据有值,你可以返回默认值.没有默认值返回空
    let newobj = {}
    for (let keysName in obj) {
        // obj[keysName] 返回的是回填的值,因此有 ||这个运算
        newobj[keysName] = obj[keysName] || ''
    }
    return newobj
}
// 搜索的时候,如果是undefined,将值进行处理
const searchDealBack = () => {
    // 将undefined转为空
    let obj = formDataViewShow.value
    let newobj = {}
    for (let keysName in obj) {
        // 因此值是undefined,说明是下拉框或者是其他,直接重置为 ''
        if (obj[keysName] === undefined) {
            newobj[keysName] = ''
        } else { 
            newobj[keysName] = obj[keysName]
        }
    }
    return newobj
}
// 重置表单事件,向上抛出去的数据
const resetHandler = () => {
    emit('resetHandler', clearDealBack())
}
// 搜索事件,向上抛出去的数据
const searchHandler = () => {
    // 获取插槽中的值
    emit('searchHandler', searchDealBack())
}
const changeHandler = () => {
    emit('searchHandler', searchDealBack())
}
let labelCol = { style: { width: '75px' } }
</script>
<style scoped>
.search-cont {
    width: 1690px;
    background: pink;
    margin-left: 30px;
}
.setdate-width {
    width: 100%;
}
.btnflex {
    text-align: right;
    padding-right: 50px !important;
}
</style>

页面使用组件

<template>
    <div class="box">
        <div class="slider"></div>
        <SearchForm class="searchbox" :resetClearInitVale="true" :listForm="listForm.list"
            @searchHandler='searchHandler' @resetHandler="resetHandler">
            <!-- <template #btn="slotProps">
                <a-radio-group v-model:value="slotProps.row.btn">
                    <a-radio-button value="01">玩耍</a-radio-button>
                    <a-radio-button value="02">摸鱼</a-radio-button>
                    <a-radio-button value="03">抓虾</a-radio-button>
                </a-radio-group>
            </template> -->
            <!-- <template #dec="slotProps">
                <a-input v-model:value="slotProps.row.dec" placeholder="Basic usage" />
            </template> -->
        </SearchForm>
        <br />
    </div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
import SearchForm from "../components/SearchForm.vue"
let listForm = reactive({
    list: [
        {
            label: '姓名', type: 'a-input',
            keyName: 'name',
            placeholder: '用户大老爷请输入',
        },
        {
            label: '班级',
            type: 'a-select',
            default: '01',// 回填的值
            placeholder: '用户大老爷请选择',
            keyName:'className',
            options: [
                { value: '01', label: '初中一班' },
                { value: '02', label: '初中二班' },
                { value: '03', label: '初中三班' }
            ]
        },
        {
            label: '阶段',
            type: 'a-select',
            placeholder: '用户大老爷请选择',
            keyName: 'jieduan',
            options: [
                { value: '01', label: '小学' },
                { value: '02', label: '高中' },
                { value: '03', label: '大学' }
            ]
        },
        {
            label: '时间',
            type: 'a-date-picker',
            keyName: 'myTime',
        },
        {
            label: '归还时间',
            type: 'a-range-picker',
            keyName: 'backTimeArr',
        },
        {
            label: '地址',
            default: '成都',
            type: 'a-input',
            keyName: 'adress',
            placeholder: '请输入',
        },
    ],
    // 后端需要的字段
    searchGiveServe: {
        adress: "成都",
        backTimeArr: "",
        className: "01",
        jieduan: "",
        myTime: "",
        name: "",
    }
})
// 重置
const resetHandler = (backMess) => { 
    listForm.searchGiveServe = backMess
    console.log('重置', listForm.searchGiveServe)
}
// 搜索
const searchHandler = (searchBack) => { 
    listForm.searchGiveServe = searchBack
    console.log('搜索', listForm.searchGiveServe)
}
// 如何在初始的时候拿到值呢?初始值需要自己手动设置
console.log('获取表单的初始值', listForm.searchGiveServe)
</script>
<style scoped lang="scss">
.box{
    display: flex;
}
.slider{
    width: 400px;
    background: pink;
}
</style>

遇见问题,这是你成长的机会,如果你能够解决,这就是收获。

相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
6月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
581 2
|
9月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1017 0
|
9月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
5月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
479 137
|
11月前
|
JavaScript
vue实现任务周期cron表达式选择组件
vue实现任务周期cron表达式选择组件
1282 4
|
10月前
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
1368 78
|
11月前
|
缓存 JavaScript 前端开发
Vue 基础语法介绍
Vue 基础语法介绍
|
8月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
611 1
|
9月前
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
620 17
|
8月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
420 0