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>