Skip to content

Commit a3ab0c2

Browse files
committed
Merge remote-tracking branch 'origin/master' into feat-1.4.0
# Conflicts: # components/vc-form/src/createBaseForm.jsx
2 parents e214277 + f58cea1 commit a3ab0c2

File tree

17 files changed

+66
-22
lines changed

17 files changed

+66
-22
lines changed

components/form/Form.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export const FormProps = {
6565
hideRequiredMark: PropTypes.bool,
6666
autoFormCreate: PropTypes.func,
6767
options: PropTypes.object,
68+
selfUpdate: PropTypes.bool,
6869
};
6970

7071
export const ValidationRule = {

components/form/FormItem.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const FormItemProps = {
3838
colon: PropTypes.bool,
3939
fieldDecoratorId: PropTypes.string,
4040
fieldDecoratorOptions: PropTypes.object,
41+
selfUpdate: PropTypes.bool,
4142
};
4243
function comeFromSlot(vnodes = [], itemVnode) {
4344
let isSlot = false;
@@ -73,6 +74,11 @@ export default {
7374
data() {
7475
return { helpShow: false };
7576
},
77+
computed: {
78+
itemSelfUpdate() {
79+
return !!(this.selfUpdate === undefined ? this.FormProps.selfUpdate : this.selfUpdate);
80+
},
81+
},
7682
created() {
7783
this.collectContext();
7884
},
@@ -463,7 +469,7 @@ export default {
463469
}
464470
const option = this.decoratorOption(vnode);
465471
if (option && option[0]) {
466-
vnodes[i] = getFieldDecorator(option[0], option[1])(vnode);
472+
vnodes[i] = getFieldDecorator(option[0], option[1], this)(vnode);
467473
}
468474
}
469475
return vnodes;
@@ -481,7 +487,7 @@ export default {
481487
let child = filterEmpty($slots.default || []);
482488
if (decoratorFormProps.form && fieldDecoratorId && child.length) {
483489
const getFieldDecorator = decoratorFormProps.form.getFieldDecorator;
484-
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions)(child[0]);
490+
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions, this)(child[0]);
485491
warning(
486492
!(child.length > 1),
487493
'`autoFormCreate` just `decorator` then first children. but you can use JSX to support multiple children',

components/form/index.zh-CN.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
| form |`Form.create()` 包装过的组件会自带 `this.form` 属性,如果使用template语法,可以使用this.$form.createForm(this, options) | object ||
88
| hideRequiredMark | 隐藏所有表单项的必选标记 | Boolean | false |
99
| layout | 表单布局 | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
10+
| selfUpdate | 自定义字段更新逻辑,说明[见下](/components/form-cn/#selfUpdate),需1.3.17版本以上 | boolean | false |
1011

1112
### 事件
1213
| 事件名称 | 说明 | 回调参数 |
@@ -175,6 +176,7 @@ validateFields(['field1', 'field2'], options, (errors, values) => {
175176
| required | 是否必填,如不设置,则会根据校验规则自动生成 | boolean | false |
176177
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' | string | |
177178
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid-cn/#Col) | |
179+
| selfUpdate | 自定义字段更新逻辑,你可以通过 Form 的 selfUpdate 进行统一设置。当和 Form 同时设置时,以 Item 为准。 说明[见下](/components/form-cn/#selfUpdate) 需1.3.17版本以上 | boolean | false |
178180

179181
### 校验规则
180182

@@ -195,3 +197,9 @@ validateFields(['field1', 'field2'], options, (errors, values) => {
195197
更多高级用法可研究 [async-validator](https://github.com/yiminghe/async-validator)
196198

197199

200+
### selfUpdate
201+
202+
设置 `selfUpdate``true` 后,`Form` 通过增量方式更新,只更新被修改的字段。大部分场景下,你只需要编写代码即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都需要进行渲染。你可以通过修改 Form.Item 取消 selfUpdate,或者在 `change` / `onValuesChange` 回调中手动调用 `this.$forceUpdate()` 更新组件。[示例]()
203+
204+
如果你并不精通 Vue,并不建议使用 selfUpdate,如果出现性能问题,可以尝试这把 Form 相关的业务独立到一个单独的组件中,减少组件渲染的消耗。
205+

components/select/index.en-US.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{key: string, label: vNodes}` | boolean | false |
2828
| maxTagCount | Max tag count to show | number | - |
2929
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
30+
| maxTagTextLength | Max text length to show | number | - |
3031
| mode | Set mode of Select | 'default' \| 'multiple' \| 'tags' | 'default' |
3132
| notFoundContent | Specify content to show when no result matches.. | string\|slot | 'Not Found' |
3233
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value |

components/select/index.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const SelectProps = {
6363
firstActiveValue: PropTypes.oneOfType([String, PropTypes.arrayOf(String)]),
6464
maxTagCount: PropTypes.number,
6565
maxTagPlaceholder: PropTypes.any,
66+
maxTagTextLength: PropTypes.number,
6667
dropdownMatchSelectWidth: PropTypes.bool,
6768
optionFilterProp: PropTypes.string,
6869
labelInValue: PropTypes.boolean,

components/select/index.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 `{key: string, label: vNodes}` 的格式 | boolean | false |
2727
| maxTagCount | 最多显示多少个 tag | number | - |
2828
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
29+
| maxTagTextLength | 最大显示的 tag 文本长度 | number | - |
2930
| mode | 设置 Select 的模式为多选或标签 | 'default' \| 'multiple' \| 'tags' \| 'combobox' | - |
3031
| notFoundContent | 当下拉列表为空时显示的内容 | string\|slot | 'Not Found' |
3132
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索 | string | value |

components/switch/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const Switch = {
1919
disabled: PropTypes.bool,
2020
checkedChildren: PropTypes.any,
2121
unCheckedChildren: PropTypes.any,
22-
tabIndex: PropTypes.number,
22+
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
2323
checked: PropTypes.bool,
2424
defaultChecked: PropTypes.bool,
2525
autoFocus: PropTypes.bool,

components/tree-select/index.en-US.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
| getPopupContainer | To set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. | Function(triggerNode) | () => document.body |
1616
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{value: string, label: VNode, halfChecked: string[]}` | boolean | false |
1717
| loadData | Load data asynchronously. | function(node) | - |
18+
| maxTagCount | Max tag count to show | number | - |
19+
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
1820
| multiple | Support multiple or not, will be `true` when enable `treeCheckable`. | boolean | false |
1921
| placeholder | Placeholder of the select input | string\|slot | - |
2022
| searchPlaceholder | Placeholder of the search input | string\|slot | - |

components/tree-select/index.zh-CN.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | () => document.body |
1616
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 value 类型从 `string` 变为 `{value: string, label: VNode, halfChecked(treeCheckStrictly 时有效): string[] }` 的格式 | boolean | false |
1717
| loadData | 异步加载数据 | function(node) | - |
18+
| maxTagCount | 最多显示多少个 tag | number | - |
19+
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
1820
| multiple | 支持多选(当设置 treeCheckable 时自动变为true) | boolean | false |
1921
| placeholder | 选择框默认文字 | string\|slot | - |
2022
| searchPlaceholder | 搜索框默认文字 | string\|slot | - |

components/vc-form/src/createBaseForm.jsx

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function createBaseForm(option = {}, mixins = []) {
6161
this.instances = {};
6262
this.cachedBind = {};
6363
this.clearedFieldMetaCache = {};
64-
64+
this.formItems = {};
6565
this.renderFields = {};
6666
this.domFields = {};
6767

@@ -182,8 +182,9 @@ function createBaseForm(option = {}, mixins = []) {
182182
return cache[action].fn;
183183
},
184184

185-
getFieldDecorator(name, fieldOption) {
185+
getFieldDecorator(name, fieldOption, formItem) {
186186
const { props, ...restProps } = this.getFieldProps(name, fieldOption);
187+
this.formItems[name] = formItem;
187188
return fieldElem => {
188189
// We should put field in record if it is rendered
189190
this.renderFields[name] = true;
@@ -351,24 +352,30 @@ function createBaseForm(option = {}, mixins = []) {
351352
setFields(maybeNestedFields, callback) {
352353
const fields = this.fieldsStore.flattenRegisteredFields(maybeNestedFields);
353354
this.fieldsStore.setFields(fields);
355+
const changedFields = Object.keys(fields).reduce(
356+
(acc, name) => set(acc, name, this.fieldsStore.getField(name)),
357+
{},
358+
);
354359
if (onFieldsChange) {
355360
const changedFields = Object.keys(fields).reduce(
356361
(acc, name) => set(acc, name, this.fieldsStore.getField(name)),
357362
{},
358363
);
359-
onFieldsChange(
360-
{
361-
[formPropName]: this.getForm(),
362-
...this.$props,
363-
},
364-
changedFields,
365-
this.fieldsStore.getNestedAllFields(),
366-
);
364+
onFieldsChange(this, changedFields, this.fieldsStore.getNestedAllFields());
367365
}
368-
if (templateContext) {
369-
templateContext.$forceUpdate();
370-
} else {
371-
this.$forceUpdate();
366+
const formContext = templateContext || this;
367+
let allUpdate = false;
368+
Object.keys(changedFields).forEach(key => {
369+
let formItem = this.formItems[key];
370+
formItem = typeof formItem === 'function' ? formItem() : formItem;
371+
if (formItem && formItem.itemSelfUpdate) {
372+
formItem.$forceUpdate();
373+
} else {
374+
allUpdate = true;
375+
}
376+
});
377+
if (allUpdate) {
378+
formContext.$forceUpdate();
372379
}
373380
this.$nextTick(() => {
374381
callback && callback();

0 commit comments

Comments
 (0)