最近项目打算重构,项目的模块几乎都是以后台查询展示的传统的增删改差模式,所以卑微的我想要自己封装一下查询form,先上效果图
子组件页面:
1 <template> 2 <div class="sumbit-form"> 3 <el-form 4 :model="value" 5 :rules="rules" 6 ref="ruleForm" 7 label-width="100px" 8 class="demo-ruleForm" 9 > 10 <slot name="formItem" /> 11 <template v-for="(item, index) in formConfig.formItemList"> 12 <el-row :key="index"> 13 <template v-for="(i, k) in item"> 14 <el-col :span="8" :key="k"> 15 <template 16 v-if=" 17 ['text', 'textarea', 'number', 'email'].indexOf(i.type) !== -1 18 " 19 > 20 <el-form-item :label="i.label" :prop="i.prop ? i.prop : ''"> 21 <el-input :type="i.type" v-model="value[i.name]"></el-input> 22 </el-form-item> 23 </template> 24 <template v-if="i.type === 'select'"> 25 <el-form-item :label="i.label" :prop="i.prop ? i.prop : ''"> 26 <el-select v-model="value[i.name]" placeholder=""> 27 <el-option 28 v-for="(j, k) in i.optList" 29 :key="k" 30 :label="j.label" 31 :value="j.value" 32 ></el-option> 33 </el-select> 34 </el-form-item> 35 </template> 36 <template 37 v-if=" 38 ['data', 'datetimerange', 'datetime'].indexOf(i.type) !== -1 39 " 40 > 41 <el-form-item :label="i.label" :prop="i.prop ? i.prop : ''"> 42 <el-date-picker 43 v-model="value[i.name]" 44 type="datetimerange" 45 range-separator="至" 46 start-placeholder="开始日期" 47 end-placeholder="结束日期" 48 value-format="yyyy-MM-dd HH:mm:ss" 49 > 50 </el-date-picker> 51 </el-form-item> 52 </template> 53 <template v-if="i.type == 'switch'"> 54 <el-form-item :label="i.label" :prop="i.prop ? i.prop : ''"> 55 <el-switch v-model="value[i.name]"></el-switch> 56 </el-form-item> 57 </template> 58 <template v-if="i.type == 'radio'"> 59 <el-form-item :label="i.label"> 60 <el-radio-group v-model="value[i.name]"> 61 <el-radio 62 v-for="(j, k) in i.optList" 63 :label="j" 64 :key="k" 65 ></el-radio> 66 </el-radio-group> 67 </el-form-item> 68 </template> 69 <template v-if="i.type === 'Checkbox'"> 70 <el-checkbox-group v-model="value[i.name]"> 71 <el-checkbox 72 v-for="ch in i.checkboxs" 73 :label="ch.value" 74 :key="ch.value" 75 >{{ ch.label }}</el-checkbox 76 > 77 </el-checkbox-group> 78 </template> 79 </el-col> 80 </template> 81 </el-row> 82 </template> 83 84 <div class="searchBtn"> 85 <el-button-group> 86 <el-button 87 v-for="(item, index) in formConfig.operate" 88 :key="index" 89 size="small" 90 :type="item.type" 91 @click.stop.prevent="item.handleClick" 92 >{{ item.name }} 93 </el-button> 94 </el-button-group> 95 <slot name="operate"></slot> 96 </div> 97 </el-form> 98 </div> 99 </template> 100 <script> 101 export default { 102 props: { 103 formConfig: { 104 type: Object, 105 default: () => {} 106 }, 107 value: { 108 type: Object, 109 default: () => {} 110 }, 111 rules: { 112 type: Object, 113 default: () => {} 114 } 115 }, 116 data() { 117 return { 118 isSearchLock: true 119 }; 120 }, 121 created() {}, 122 methods: { 123 //子组件校验,传递到父组件 124 validateForm() { 126 let flag = null; 127 if (this.isSearchLock) { 128 this.$refs["ruleForm"].validate(valid => { 129 let vm = this; 130 if (valid) { 131 flag = true; 132 vm.isSearchLock = flag; 133 } else { 134 flag = false; 135 vm.isSearchLock = flag; 136 this.$message.error("保存信息不完整,请继续填写完整"); 137 setTimeout(function() { 138 vm.isSearchLock = true; 139 }, 2000); 140 } 141 }); 142 return flag; 143 } 144 }, 145 resetFields() { 146 this.$refs["ruleForm"].resetFields(); 147 } 148 }, 149 mounted() {} 150 }; 151 </script> 152 <style lang="less"> 153 .el-form-item__content { 154 .el-date-editor--datetimerange { 155 width: 100%; 156 } 157 } 158 .searchBtn { 159 text-align: center; 160 .el-button { 161 background-color: #4a91d7; 162 width: 96px; 163 color: #fff; 164 &:first-child { 165 margin-right: 5px; 166 } 167 &:hover { 168 background-color: #257ccd; 169 border-color: #257ccd; 170 } 171 } 172 } 173 </style>
父组件里面调用
1 <flight-form 2 ref="childRules" 3 :formConfig="formConfig" 4 :value="form" 5 :rules="rules" 6 ></flight-form> 7 <script> 8 import flightForm from "@/components/flightForm.vue"; 9 export default{ 10 components: { 11 flightForm , 12 13 }, 14 data() { 15 return { 16 formConfig: { 17 formItemList: [ 18 [ 19 { 20 type: "text", 21 prop: "airport", 22 label: "站点", 23 name: "airport", 24 placeholder: "请输入站点" 25 }, 26 { 27 type: "select", 28 prop: "importOrExport", 29 label: "进出港", 30 name: "importOrExport", 31 placeholder: "请输入进出港", 32 optList: [ 33 { 34 value: "", 35 label: "" 36 }, 37 { 38 value: "进港", 39 label: "进港" 40 }, 41 { 42 value: "出港", 43 label: "出港" 44 } 45 ] 46 }, 47 { 48 type: "select", 49 prop: "mainOrSubBill", 50 name: "mainOrSubBill", 51 label: "主分单", 52 53 placeholder: "请输入主分单", 54 optList: [ 55 { 56 value: "", 57 label: "" 58 }, 59 { 60 value: "主分", 61 label: "主分" 62 }, 63 { 64 value: "主单", 65 label: "主单" 66 } 67 ] 68 } 69 ], 70 [ 71 { 72 type: "datetimerange", 73 name: "pickerdata", 74 label: "选择时间", 75 prop: "pickerdata", 76 dateFormate: "yyyy-MM-dd HH:mm:ss" 77 }, 78 { 79 type: "text", 80 name: "largeClass", 81 prop: "largeClass", 82 label: "大类", 83 placeholder: "请输入大类" 84 }, 85 { 86 type: "select", 87 name: "isDomestic", 88 prop: "isDomestic", 89 value: "国内", 90 label: "国内/国际", 91 placeholder: "请输入国内/国际", 92 optList: [ 93 { 94 value: "", 95 label: "" 96 }, 97 { 98 value: "国内", 99 label: "国内" 100 }, 101 { 102 value: "国际", 103 label: "国际" 104 } 105 ] 106 } 107 ], 108 [ 109 { 110 type: "switch", 111 name: "save", 112 prop: "save", 113 label: "保存" 114 }, 115 { 116 type: "radio", 117 name: "radio", 118 prop: "radio", 119 label: "活动类型", 120 optList: ["演唱会", "球赛"] 121 }, 122 { 123 type: "Checkbox", 124 label: "爱好", 125 prop: "Checkbox", 126 name: "Checkbox", 127 checkboxs: [ 128 { label: "羽毛球", value: "badminton" }, 129 { label: "篮球", value: "basketball" }, 130 { label: "足球", value: "football" }, 131 { label: "兵乓球", value: "pong" } 132 ] 133 } 134 ] 135 ], 136 137 operate: [ 138 { 139 type: "primary", 140 name: "查询", 141 handleClick: this.search 142 }, 143 { 144 type: "primary", 145 name: "重置", 146 handleClick: this.add 147 } 148 ] 149 }, 150 rules: { 151 airport: [{ required: true, message: "请输入站点", trigger: "blur" }], 152 importOrExport: [ 153 { required: true, message: "请输入进出港", trigger: "blur" } 154 ], 155 largeClass: [ 156 { required: true, message: "请输入大类", trigger: "blur" } 157 ], 158 mainOrSubBill: [ 159 { required: true, message: "请输入主分单", trigger: "blur" } 160 ], 161 isDomestic: [ 162 { required: true, message: "请输入国内/国际", trigger: "blur" } 163 ], 164 pickerdata: [ 165 { required: true, message: "请输入时间", trigger: "change" } 166 ] 167 }, 168 form: { 169 isDomestic: "国内", 170 mainOrSubBill: "主分", 171 importOrExport: "进港", 172 airport: "", 173 largeClass: "", 174 Checkbox: [], 175 pickerdata: [], 176 save: false, 177 radio: "" 178 }, 179 } 180 }, 181 methods: { 182 // 查询 183 search() { 184 let flag = this.$refs["childRules"].validateForm(); 185 if (flag) { 186 console.log(this.form); 187 } 188 }, 189 // 新增或重置 190 add() { 191 this.$refs["childRules"].resetFields(); 192 }, 193 }, 194 } 195 } 196 </script>
父组件里面的form传给子组件是传默认值的,
卑微前端,记录自己的项目封装的组件,方便以后自己用,如果有哪里不合理,请各路大神多多指教。