Commit ef2583ca7276d10d21d3d36194ffc03684286993
1 parent
463409cd
Exists in
master
and in
2 other branches
feat: 修改SchemaForm
Showing
2 changed files
with
115 additions
and
24 deletions
Show diff stats
examples/views/docs/component/schema-form.md
| @@ -228,6 +228,104 @@ export default { | @@ -228,6 +228,104 @@ export default { | ||
| 228 | 228 | ||
| 229 | ::: | 229 | ::: |
| 230 | 230 | ||
| 231 | +## 显示状态 | ||
| 232 | + | ||
| 233 | +支持配置`if`、`show`对表单项进行`v-if`、`v-show`逻辑的设置。 | ||
| 234 | + | ||
| 235 | +::: snippet 隐藏表单项的示例 | ||
| 236 | + | ||
| 237 | +```html | ||
| 238 | +<template> | ||
| 239 | + <z-schema-form v-model="form" :schema="schema"></z-schema-form> | ||
| 240 | +</template> | ||
| 241 | + | ||
| 242 | +<script> | ||
| 243 | +export default { | ||
| 244 | + data() { | ||
| 245 | + return { | ||
| 246 | + form: { | ||
| 247 | + name: '张三', | ||
| 248 | + age: 27, | ||
| 249 | + address: '上海市青浦区华新镇纪鹤公路1988号', | ||
| 250 | + }, | ||
| 251 | + schema: { | ||
| 252 | + props: { labelWidth: '70px', size: 'small', span: 12 }, | ||
| 253 | + items: [ | ||
| 254 | + { is: 'el-input', prop: 'id', props: { disabled: true }, label: 'ID', show: false }, | ||
| 255 | + { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] }, | ||
| 256 | + { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }] }, | ||
| 257 | + { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24 }, | ||
| 258 | + { is: 'el-input', prop: 'package', label: '包裹', span: 24, if: false }, | ||
| 259 | + ] | ||
| 260 | + }, | ||
| 261 | + }; | ||
| 262 | + }, | ||
| 263 | +}; | ||
| 264 | +</script> | ||
| 265 | +``` | ||
| 266 | + | ||
| 267 | +::: | ||
| 268 | + | ||
| 269 | +## 动态规则 | ||
| 270 | + | ||
| 271 | +某些情况下,表单中的某一项根据另一项的值来做当前项`显示状态`、`校验规则`、`标签名称`的动态判断。支持将任意表单配置项的任意参数改写为`function`类型,参数提供`value`、`model`、`onInput`等。 | ||
| 272 | + | ||
| 273 | +::: snippet 动态规则仅在配置项中有效,配置项子节点中无效 | ||
| 274 | + | ||
| 275 | +```html | ||
| 276 | +<template> | ||
| 277 | + <z-schema-form v-model="form" :schema="schema" @submit="onSubmit" @reset="onReset" @cancel="onCancel"> | ||
| 278 | + <template #footer="{ submit, reset, cancel }"> | ||
| 279 | + <z-form-item> | ||
| 280 | + <el-button type="primary" @click="submit">确定</el-button> | ||
| 281 | + <el-button plain @click="reset">重置</el-button> | ||
| 282 | + <el-button plain @click="cancel">取消</el-button> | ||
| 283 | + </z-form-item> | ||
| 284 | + </template> | ||
| 285 | + </z-schema-form> | ||
| 286 | +</template> | ||
| 287 | + | ||
| 288 | +<script> | ||
| 289 | +export default { | ||
| 290 | + data() { | ||
| 291 | + return { | ||
| 292 | + form: { | ||
| 293 | + name: '', | ||
| 294 | + age: '', | ||
| 295 | + address: '', | ||
| 296 | + }, | ||
| 297 | + schema: { | ||
| 298 | + props: { labelWidth: '70px', size: 'small', span: 12 }, | ||
| 299 | + items: [ | ||
| 300 | + { is: 'el-input', prop: 'name', label: '姓名', rules: [{ required: true, message: '请输入姓名' }] }, | ||
| 301 | + { is: 'el-input-number', prop: 'age', label: '年龄', rules: [{ required: true, message: '请输入有效年龄' }], if({ model }) { return model.name } }, | ||
| 302 | + { is: 'el-input', props: { type: 'textarea' }, prop: 'address', label: '住址', span: 24, | ||
| 303 | + if({ model }) { return model.age }, | ||
| 304 | + rules({ model }) { | ||
| 305 | + return model.address ? [{ required: true, min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'input' }] : [{ required: false }]; | ||
| 306 | + } | ||
| 307 | + }, | ||
| 308 | + ] | ||
| 309 | + }, | ||
| 310 | + }; | ||
| 311 | + }, | ||
| 312 | + methods: { | ||
| 313 | + onSubmit(value) { | ||
| 314 | + console.log(value); | ||
| 315 | + }, | ||
| 316 | + onReset() { | ||
| 317 | + console.log('reset'); | ||
| 318 | + }, | ||
| 319 | + onCancel() { | ||
| 320 | + console.log('cancal'); | ||
| 321 | + } | ||
| 322 | + } | ||
| 323 | +}; | ||
| 324 | +</script> | ||
| 325 | +``` | ||
| 326 | + | ||
| 327 | +::: | ||
| 328 | + | ||
| 231 | ## 配置复用 | 329 | ## 配置复用 |
| 232 | 330 | ||
| 233 | 因为与`z-form`、`z-form-item`用法相同,所以除了可以用作表单以外,也可用作详情展示,同时因为本身是schema配置项,所以可以做到表单和详情**配置复用**。 | 331 | 因为与`z-form`、`z-form-item`用法相同,所以除了可以用作表单以外,也可用作详情展示,同时因为本身是schema配置项,所以可以做到表单和详情**配置复用**。 |
packages/schema-form/index.vue
| @@ -2,32 +2,16 @@ | @@ -2,32 +2,16 @@ | ||
| 2 | <z-form ref="form" v-model="model" v-bind="schema.props" v-on="schema.props"> | 2 | <z-form ref="form" v-model="model" v-bind="schema.props" v-on="schema.props"> |
| 3 | <template v-for="(item, index) in schema.items"> | 3 | <template v-for="(item, index) in schema.items"> |
| 4 | <template v-if="item.is"> | 4 | <template v-if="item.is"> |
| 5 | - <z-form-item v-bind="keywordFilter(item)" :key="index"> | ||
| 6 | - <slot | ||
| 7 | - v-if="$scopedSlots[item.prop]" | ||
| 8 | - :name="item.prop" | ||
| 9 | - :value="get(model, item.prop)" | ||
| 10 | - :onInput="value => onComponentInput({ value, item })" | ||
| 11 | - :props="{ value: get(model, item.prop) }" | ||
| 12 | - :listeners="{ input: value => onComponentInput({ value, item }) }" | ||
| 13 | - v-bind="slotProps" | ||
| 14 | - > | ||
| 15 | - </slot> | 5 | + <z-form-item v-if="bindParam(item, 'if', true)" v-show="bindParam(item, 'show', true)" v-bind="bindItemProps(item)" :key="index"> |
| 6 | + <slot v-if="$scopedSlots[item.prop]" :name="item.prop" :value="get(model, item.prop)" :onInput="value => onComponentInput({ value, item })" v-bind="slotProps"> </slot> | ||
| 16 | <item-render v-else :item="item" :value="get(model, item.prop)" :onInput="value => onComponentInput({ value, item })"></item-render> | 7 | <item-render v-else :item="item" :value="get(model, item.prop)" :onInput="value => onComponentInput({ value, item })"></item-render> |
| 17 | <slot :name="`label-${item.prop}`" slot="label" v-bind="slotProps"></slot> | 8 | <slot :name="`label-${item.prop}`" slot="label" v-bind="slotProps"></slot> |
| 18 | <slot :name="`error-${item.prop}`" slot="error" v-bind="slotProps"></slot> | 9 | <slot :name="`error-${item.prop}`" slot="error" v-bind="slotProps"></slot> |
| 19 | </z-form-item> | 10 | </z-form-item> |
| 20 | </template> | 11 | </template> |
| 21 | <template v-else> | 12 | <template v-else> |
| 22 | - <z-form-item v-bind="keywordFilter(item)" :key="index" :value="get(model, item.prop)"> | ||
| 23 | - <slot | ||
| 24 | - :name="item.prop" | ||
| 25 | - :value="get(model, item.prop)" | ||
| 26 | - :onInput="value => onComponentInput({ value, item })" | ||
| 27 | - :props="{ value: get(model, item.prop) }" | ||
| 28 | - :listeners="{ input: value => onComponentInput({ value, item }) }" | ||
| 29 | - v-bind="slotProps" | ||
| 30 | - ></slot> | 13 | + <z-form-item v-if="bindParam(item, 'if', true)" v-show="bindParam(item, 'show', true)" v-bind="bindItemProps(item)" :key="index" :value="get(model, item.prop)"> |
| 14 | + <slot :name="item.prop" :value="get(model, item.prop)" :onInput="value => onComponentInput({ value, item })" v-bind="slotProps"></slot> | ||
| 31 | </z-form-item> | 15 | </z-form-item> |
| 32 | </template> | 16 | </template> |
| 33 | </template> | 17 | </template> |
| @@ -118,6 +102,19 @@ export default { | @@ -118,6 +102,19 @@ export default { | ||
| 118 | }, | 102 | }, |
| 119 | methods: { | 103 | methods: { |
| 120 | get, | 104 | get, |
| 105 | + bindParam(item, key, def) { | ||
| 106 | + if (typeof item[key] === 'function') { | ||
| 107 | + return item[key]({ model: this.model }); | ||
| 108 | + } | ||
| 109 | + return def || item[key]; | ||
| 110 | + }, | ||
| 111 | + bindItemProps(item) { | ||
| 112 | + const { children, is, props, on, ...other } = item || {}; | ||
| 113 | + return Object.keys(other).reduce((result, current) => { | ||
| 114 | + result = { ...result, [current]: this.bindParam(item, current, item[current]) }; | ||
| 115 | + return result; | ||
| 116 | + }, {}); | ||
| 117 | + }, | ||
| 121 | validate(callback) { | 118 | validate(callback) { |
| 122 | return this.$refs.form.validate(callback); | 119 | return this.$refs.form.validate(callback); |
| 123 | }, | 120 | }, |
| @@ -130,10 +127,6 @@ export default { | @@ -130,10 +127,6 @@ export default { | ||
| 130 | clearValidate(props) { | 127 | clearValidate(props) { |
| 131 | return this.$refs.form.clearValidate(props); | 128 | return this.$refs.form.clearValidate(props); |
| 132 | }, | 129 | }, |
| 133 | - keywordFilter(val = {}) { | ||
| 134 | - const { children, is, ...other } = val; | ||
| 135 | - return other; | ||
| 136 | - }, | ||
| 137 | onComponentInput({ value, item }) { | 130 | onComponentInput({ value, item }) { |
| 138 | set(this.model, item.prop, value); | 131 | set(this.model, item.prop, value); |
| 139 | }, | 132 | }, |