فهرست منبع

!996 修改search组件,让其能与父组件数据进行双向绑定。新增computed拦截v-model插件,在search组件中有使用。
Merge pull request !996 from xin-saul/next

zuohuaijun 2 سال پیش
والد
کامیت
aa52eac2dd
2فایلهای تغییر یافته به همراه59 افزوده شده و 54 حذف شده
  1. 36 54
      Web/src/components/table/search.vue
  2. 23 0
      Web/src/utils/saulVModel.ts

+ 36 - 54
Web/src/components/table/search.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="table-search-container" v-if="props.search.length > 0">
-		<el-form ref="tableSearchRef" :model="state.form" label-width="100px" class="table-form">
+		<el-form ref="tableSearchRef" :model="model" label-width="100px" class="table-form">
 			<el-row :gutter="20">
 				<!-- <el-col :xs="12" :sm="8" :md="8" :lg="6" :xl="4" class="mb20"></el-col> -->
 				<el-col :xs="12" :sm="5" :md="5" :lg="6" :xl="4" class="mb20" v-for="(val, key) in search" :key="key" v-show="key < 3 || state.isToggle">
@@ -12,7 +12,7 @@
 							:rules="[{ required: val.required, message: `${val.label}不能为空`, trigger: val.type === 'input' ? 'blur' : 'change' }]"
 						>
 							<el-input
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 								v-bind="val.comProps"
 								:placeholder="val.placeholder"
 								:clearable="!val.required"
@@ -22,7 +22,7 @@
 								class="w100"
 							/>
 							<el-date-picker
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 								v-bind="val.comProps"
 								type="date"
 								:placeholder="val.placeholder"
@@ -32,7 +32,7 @@
 								class="w100"
 							/>
 							<el-date-picker
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 								v-bind="val.comProps"
 								type="monthrange"
 								value-format="YYYY/MM/DD"
@@ -43,7 +43,7 @@
 								class="w100"
 							/>
 							<el-date-picker
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 								v-bind="val.comProps"
 								type="daterange"
 								value-format="YYYY/MM/DD"
@@ -54,7 +54,7 @@
 								class="w100"
 							/>
 							<el-select
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 								v-bind="val.comProps"
 								:clearable="!val.required"
 								:placeholder="val.placeholder"
@@ -74,7 +74,7 @@
 								@change="val.change"
 								class="w100"
 								v-bind="val.comProps"
-								v-model="state.form[val.prop]"
+								v-model="model[val.prop]"
 							>
 							</el-cascader>
 						</el-form-item>
@@ -92,10 +92,10 @@
 						</template>
 						<div>
 							<!-- 使用el-button-group会导致具有type属性的按钮的右边框无法显示 -->
-							<!-- <el-button-group> -->
-							<el-button plain type="primary" icon="ele-Search" @click="onSearch(tableSearchRef)"> 查询 </el-button>
-							<el-button icon="ele-Refresh" @click="onReset(tableSearchRef)" style="margin-left: 12px"> 重置 </el-button>
-							<!-- </el-button-group> -->
+							<el-button-group>
+								<el-button plain type="primary" icon="ele-Search" @click="onSearch(tableSearchRef)"> 查询 </el-button>
+								<el-button icon="ele-Refresh" @click="onReset(tableSearchRef)" style="margin-left: 12px"> 重置 </el-button>
+							</el-button-group>
 						</div>
 					</el-form-item>
 				</el-col>
@@ -105,8 +105,9 @@
 </template>
 
 <script setup lang="ts" name="makeTableDemoSearch">
-import { reactive, ref, onMounted, watch } from 'vue';
-import type { FormInstance } from 'element-plus';
+import { reactive, ref } from 'vue'
+import type { FormInstance } from 'element-plus'
+import { saulVModel } from '/@/utils/saulVModel'
 
 // 定义父组件传过来的值
 const props = defineProps({
@@ -114,67 +115,48 @@ const props = defineProps({
 	// 可带入comProps属性,和使用的控件属性对应
 	search: {
 		type: Array<TableSearchType>,
-		default: () => [],
+		default: () => []
 	},
 	reset: {
 		type: Object,
-		default: () => {},
+		default: () => {}
 	},
-	param: {
+	modelValue: {
 		type: Object,
-		default: () => {},
-	},
-});
+		default: () => {}
+	}
+})
 
 // 定义子组件向父组件传值/事件
-const emit = defineEmits(['search', 'reset']);
+const emit = defineEmits(['search', 'reset', 'update:modelValue'])
 
 // 定义变量内容
-const tableSearchRef = ref<FormInstance>();
+const tableSearchRef = ref<FormInstance>()
 const state = reactive({
-	form: {} as any,
 	isToggle: false,
 	cascaderProps: { checkStrictly: true, emitPath: false, value: 'id', label: 'name', expandTrigger: 'hover' },
-});
-watch(
-	() => props.param,
-	(value) => {
-		if (value) {
-			state.form = Object.assign({}, { ...value });
-		}
-	},
-	{
-		immediate: true,
-		deep: true,
-	}
-);
+})
+
+const model = saulVModel(props, 'modelValue', emit)
+
 // 查询
 const onSearch = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
+	if (!formEl) return
 	formEl.validate((valid: boolean) => {
 		if (valid) {
-			emit('search', state.form);
+			emit('search')
 		} else {
-			return false;
+			return false
 		}
-	});
-};
+	})
+}
+
 // 重置
 const onReset = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	emit('reset', state.form);
-	emit('search', state.form);
-};
-// // 初始化 form 字段,取自父组件 search.prop
-// const initFormField = () => {
-// 	if (props.search.length <= 0) return false;
-// 	props.search.forEach((v) => (state.form[v.prop] = ''));
-// };
-// 页面加载时
-onMounted(() => {
-	// initFormField();
-});
+	if (!formEl) return
+	formEl.resetFields()
+	emit('reset')
+}
 </script>
 
 <style scoped lang="scss">

+ 23 - 0
Web/src/utils/saulVModel.ts

@@ -0,0 +1,23 @@
+import { computed } from 'vue'
+export const saulVModel = <T extends Readonly<{ [k: string]: any }>, K extends keyof T>(
+  props: T,
+  propName: K,
+  emit: (...args: any[]) => void
+) => {
+  return computed({
+    get() {
+      if (typeof props[propName] === 'object') {
+        return new Proxy(props[propName], {
+          set(obj, name, val) {
+            emit(`update:${String(propName)}`, { ...obj, [name]: val })
+            return true
+          }
+        })
+      }
+      return props[propName]
+    },
+    set(val) {
+      emit(`update:${String(propName)}`, val)
+    }
+  })
+}