#
tokens: 36141/50000 1/1152 files (page 48/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 48 of 52. Use http://codebase.md/alibaba/formily?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .all-contributorsrc
├── .codecov.yml
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .github
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows
│       ├── check-pr-title.yml
│       ├── ci.yml
│       ├── commitlint.yml
│       ├── issue-open-check.yml
│       ├── package-size.yml
│       └── pr-welcome.yml
├── .gitignore
├── .prettierrc.js
├── .umirc.js
├── .vscode
│   └── cspell.json
├── .yarnrc
├── CHANGELOG.md
├── commitlint.config.js
├── devtools
│   ├── .eslintrc
│   └── chrome-extension
│       ├── .npmignore
│       ├── assets
│       │   └── img
│       │       ├── loading.svg
│       │       └── logo
│       │           ├── 128x128.png
│       │           ├── 16x16.png
│       │           ├── 38x38.png
│       │           ├── 48x48.png
│       │           ├── error.png
│       │           ├── gray.png
│       │           └── scalable.png
│       ├── config
│       │   ├── webpack.base.ts
│       │   ├── webpack.dev.ts
│       │   └── webpack.prod.ts
│       ├── LICENSE.md
│       ├── package.json
│       ├── src
│       │   ├── app
│       │   │   ├── components
│       │   │   │   ├── FieldTree.tsx
│       │   │   │   ├── filter.ts
│       │   │   │   ├── LeftPanel.tsx
│       │   │   │   ├── RightPanel.tsx
│       │   │   │   ├── SearchBox.tsx
│       │   │   │   └── Tabs.tsx
│       │   │   ├── demo.tsx
│       │   │   └── index.tsx
│       │   └── extension
│       │       ├── backend.ts
│       │       ├── background.ts
│       │       ├── content.ts
│       │       ├── devpanel.tsx
│       │       ├── devtools.tsx
│       │       ├── inject.ts
│       │       ├── manifest.json
│       │       ├── popup.tsx
│       │       └── views
│       │           ├── devpanel.ejs
│       │           ├── devtools.ejs
│       │           └── popup.ejs
│       ├── tsconfig.build.json
│       └── tsconfig.json
├── docs
│   ├── functions
│   │   ├── contributors.ts
│   │   └── npm-search.ts
│   ├── guide
│   │   ├── advanced
│   │   │   ├── async.md
│   │   │   ├── async.zh-CN.md
│   │   │   ├── build.md
│   │   │   ├── build.zh-CN.md
│   │   │   ├── business-logic.md
│   │   │   ├── business-logic.zh-CN.md
│   │   │   ├── calculator.md
│   │   │   ├── calculator.zh-CN.md
│   │   │   ├── controlled.md
│   │   │   ├── controlled.zh-CN.md
│   │   │   ├── custom.md
│   │   │   ├── custom.zh-CN.md
│   │   │   ├── destructor.md
│   │   │   ├── destructor.zh-CN.md
│   │   │   ├── input.less
│   │   │   ├── layout.md
│   │   │   ├── layout.zh-CN.md
│   │   │   ├── linkages.md
│   │   │   ├── linkages.zh-CN.md
│   │   │   ├── validate.md
│   │   │   └── validate.zh-CN.md
│   │   ├── contribution.md
│   │   ├── contribution.zh-CN.md
│   │   ├── form-builder.md
│   │   ├── form-builder.zh-CN.md
│   │   ├── index.md
│   │   ├── index.zh-CN.md
│   │   ├── issue-helper.md
│   │   ├── issue-helper.zh-CN.md
│   │   ├── learn-formily.md
│   │   ├── learn-formily.zh-CN.md
│   │   ├── quick-start.md
│   │   ├── quick-start.zh-CN.md
│   │   ├── scenes
│   │   │   ├── dialog-drawer.md
│   │   │   ├── dialog-drawer.zh-CN.md
│   │   │   ├── edit-detail.md
│   │   │   ├── edit-detail.zh-CN.md
│   │   │   ├── index.less
│   │   │   ├── login-register.md
│   │   │   ├── login-register.zh-CN.md
│   │   │   ├── more.md
│   │   │   ├── more.zh-CN.md
│   │   │   ├── query-list.md
│   │   │   ├── query-list.zh-CN.md
│   │   │   ├── step-form.md
│   │   │   ├── step-form.zh-CN.md
│   │   │   ├── tab-form.md
│   │   │   ├── tab-form.zh-CN.md
│   │   │   └── VerifyCode.tsx
│   │   ├── upgrade.md
│   │   └── upgrade.zh-CN.md
│   ├── index.md
│   ├── index.zh-CN.md
│   └── site
│       ├── Contributors.less
│       ├── Contributors.tsx
│       ├── QrCode.less
│       ├── QrCode.tsx
│       ├── Section.less
│       ├── Section.tsx
│       └── styles.less
├── global.config.ts
├── jest.config.js
├── lerna.json
├── LICENSE.md
├── package.json
├── packages
│   ├── .eslintrc
│   ├── antd
│   │   ├── __tests__
│   │   │   ├── moment.spec.ts
│   │   │   └── sideEffects.spec.ts
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── components
│   │   │   │   ├── ArrayCards.md
│   │   │   │   ├── ArrayCards.zh-CN.md
│   │   │   │   ├── ArrayCollapse.md
│   │   │   │   ├── ArrayCollapse.zh-CN.md
│   │   │   │   ├── ArrayItems.md
│   │   │   │   ├── ArrayItems.zh-CN.md
│   │   │   │   ├── ArrayTable.md
│   │   │   │   ├── ArrayTable.zh-CN.md
│   │   │   │   ├── ArrayTabs.md
│   │   │   │   ├── ArrayTabs.zh-CN.md
│   │   │   │   ├── Cascader.md
│   │   │   │   ├── Cascader.zh-CN.md
│   │   │   │   ├── Checkbox.md
│   │   │   │   ├── Checkbox.zh-CN.md
│   │   │   │   ├── DatePicker.md
│   │   │   │   ├── DatePicker.zh-CN.md
│   │   │   │   ├── Editable.md
│   │   │   │   ├── Editable.zh-CN.md
│   │   │   │   ├── Form.md
│   │   │   │   ├── Form.zh-CN.md
│   │   │   │   ├── FormButtonGroup.md
│   │   │   │   ├── FormButtonGroup.zh-CN.md
│   │   │   │   ├── FormCollapse.md
│   │   │   │   ├── FormCollapse.zh-CN.md
│   │   │   │   ├── FormDialog.md
│   │   │   │   ├── FormDialog.zh-CN.md
│   │   │   │   ├── FormDrawer.md
│   │   │   │   ├── FormDrawer.zh-CN.md
│   │   │   │   ├── FormGrid.md
│   │   │   │   ├── FormGrid.zh-CN.md
│   │   │   │   ├── FormItem.md
│   │   │   │   ├── FormItem.zh-CN.md
│   │   │   │   ├── FormLayout.md
│   │   │   │   ├── FormLayout.zh-CN.md
│   │   │   │   ├── FormStep.md
│   │   │   │   ├── FormStep.zh-CN.md
│   │   │   │   ├── FormTab.md
│   │   │   │   ├── FormTab.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── Input.md
│   │   │   │   ├── Input.zh-CN.md
│   │   │   │   ├── NumberPicker.md
│   │   │   │   ├── NumberPicker.zh-CN.md
│   │   │   │   ├── Password.md
│   │   │   │   ├── Password.zh-CN.md
│   │   │   │   ├── PreviewText.md
│   │   │   │   ├── PreviewText.zh-CN.md
│   │   │   │   ├── Radio.md
│   │   │   │   ├── Radio.zh-CN.md
│   │   │   │   ├── Reset.md
│   │   │   │   ├── Reset.zh-CN.md
│   │   │   │   ├── Select.md
│   │   │   │   ├── Select.zh-CN.md
│   │   │   │   ├── SelectTable.md
│   │   │   │   ├── SelectTable.zh-CN.md
│   │   │   │   ├── Space.md
│   │   │   │   ├── Space.zh-CN.md
│   │   │   │   ├── Submit.md
│   │   │   │   ├── Submit.zh-CN.md
│   │   │   │   ├── Switch.md
│   │   │   │   ├── Switch.zh-CN.md
│   │   │   │   ├── TimePicker.md
│   │   │   │   ├── TimePicker.zh-CN.md
│   │   │   │   ├── Transfer.md
│   │   │   │   ├── Transfer.zh-CN.md
│   │   │   │   ├── TreeSelect.md
│   │   │   │   ├── TreeSelect.zh-CN.md
│   │   │   │   ├── Upload.md
│   │   │   │   └── Upload.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── hooks
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useClickAway.ts
│   │   │   │   │   └── usePrefixCls.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── loading.ts
│   │   │   │   ├── moment.ts
│   │   │   │   ├── pickDataProps.ts
│   │   │   │   ├── portal.tsx
│   │   │   │   ├── render.ts
│   │   │   │   └── sort.tsx
│   │   │   ├── array-base
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── array-tabs
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.less
│   │   │   │   ├── grid.less
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── form-layout
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── number-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.tsx
│   │   │   │   ├── PasswordStrength.tsx
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── style.less
│   │   │   │   ├── style.ts
│   │   │   │   ├── useCheckSlackly.tsx
│   │   │   │   ├── useFilterOptions.tsx
│   │   │   │   ├── useFlatOptions.tsx
│   │   │   │   ├── useSize.tsx
│   │   │   │   ├── useTitleAddon.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── space
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── style.less
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── tree-select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.tsx
│   │   │       ├── placeholder.ts
│   │   │       └── style.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── benchmark
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   └── index.tsx
│   │   ├── template.ejs
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   ├── webpack.base.ts
│   │   ├── webpack.dev.ts
│   │   └── webpack.prod.ts
│   ├── core
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── entry
│   │   │   │   │   ├── ActionResponse.less
│   │   │   │   │   ├── ActionResponse.tsx
│   │   │   │   │   ├── createForm.md
│   │   │   │   │   ├── createForm.zh-CN.md
│   │   │   │   │   ├── FieldEffectHooks.md
│   │   │   │   │   ├── FieldEffectHooks.zh-CN.md
│   │   │   │   │   ├── FormChecker.md
│   │   │   │   │   ├── FormChecker.zh-CN.md
│   │   │   │   │   ├── FormEffectHooks.md
│   │   │   │   │   ├── FormEffectHooks.zh-CN.md
│   │   │   │   │   ├── FormHooksAPI.md
│   │   │   │   │   ├── FormHooksAPI.zh-CN.md
│   │   │   │   │   ├── FormPath.md
│   │   │   │   │   ├── FormPath.zh-CN.md
│   │   │   │   │   ├── FormValidatorRegistry.md
│   │   │   │   │   └── FormValidatorRegistry.zh-CN.md
│   │   │   │   └── models
│   │   │   │       ├── ArrayField.md
│   │   │   │       ├── ArrayField.zh-CN.md
│   │   │   │       ├── Field.md
│   │   │   │       ├── Field.zh-CN.md
│   │   │   │       ├── Form.md
│   │   │   │       ├── Form.zh-CN.md
│   │   │   │       ├── ObjectField.md
│   │   │   │       ├── ObjectField.zh-CN.md
│   │   │   │       ├── Query.md
│   │   │   │       ├── Query.zh-CN.md
│   │   │   │       ├── VoidField.md
│   │   │   │       └── VoidField.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── architecture.md
│   │   │   │   ├── architecture.zh-CN.md
│   │   │   │   ├── field.md
│   │   │   │   ├── field.zh-CN.md
│   │   │   │   ├── form.md
│   │   │   │   ├── form.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── mvvm.md
│   │   │   │   ├── mvvm.zh-CN.md
│   │   │   │   ├── values.md
│   │   │   │   └── values.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── array.spec.ts
│   │   │   │   ├── effects.spec.ts
│   │   │   │   ├── externals.spec.ts
│   │   │   │   ├── field.spec.ts
│   │   │   │   ├── form.spec.ts
│   │   │   │   ├── graph.spec.ts
│   │   │   │   ├── heart.spec.ts
│   │   │   │   ├── internals.spec.ts
│   │   │   │   ├── lifecycle.spec.ts
│   │   │   │   ├── object.spec.ts
│   │   │   │   ├── shared.ts
│   │   │   │   └── void.spec.ts
│   │   │   ├── effects
│   │   │   │   ├── index.ts
│   │   │   │   ├── onFieldEffects.ts
│   │   │   │   └── onFormEffects.ts
│   │   │   ├── global.d.ts
│   │   │   ├── index.ts
│   │   │   ├── models
│   │   │   │   ├── ArrayField.ts
│   │   │   │   ├── BaseField.ts
│   │   │   │   ├── Field.ts
│   │   │   │   ├── Form.ts
│   │   │   │   ├── Graph.ts
│   │   │   │   ├── Heart.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── LifeCycle.ts
│   │   │   │   ├── ObjectField.ts
│   │   │   │   ├── Query.ts
│   │   │   │   ├── types.ts
│   │   │   │   └── VoidField.ts
│   │   │   ├── shared
│   │   │   │   ├── checkers.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── effective.ts
│   │   │   │   ├── externals.ts
│   │   │   │   └── internals.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── element
│   │   ├── .npmignore
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── .vuepress
│   │   │   │   ├── components
│   │   │   │   │   ├── createCodeSandBox.js
│   │   │   │   │   ├── dumi-previewer.vue
│   │   │   │   │   └── highlight.js
│   │   │   │   ├── config.js
│   │   │   │   ├── enhanceApp.js
│   │   │   │   ├── styles
│   │   │   │   │   └── index.styl
│   │   │   │   └── util.js
│   │   │   ├── demos
│   │   │   │   ├── guide
│   │   │   │   │   ├── array-cards
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-collapse
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-items
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-table
│   │   │   │   │   │   ├── effects-json-schema.vue
│   │   │   │   │   │   ├── effects-markup-schema.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── array-tabs
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── cascader
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── checkbox
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── date-picker
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── editable
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-button-group.vue
│   │   │   │   │   ├── form-collapse
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form-dialog
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-drawer
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-grid
│   │   │   │   │   │   ├── form.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── native.vue
│   │   │   │   │   ├── form-item
│   │   │   │   │   │   ├── bordered-none.vue
│   │   │   │   │   │   ├── common.vue
│   │   │   │   │   │   ├── feedback.vue
│   │   │   │   │   │   ├── inset.vue
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   ├── size.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-layout
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── form-step
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form-tab
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   └── markup-schema.vue
│   │   │   │   │   ├── form.vue
│   │   │   │   │   ├── input
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── input-number
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── password
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── preview-text
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   └── extend.vue
│   │   │   │   │   ├── radio
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── reset
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   ├── force.vue
│   │   │   │   │   │   └── validate.vue
│   │   │   │   │   ├── select
│   │   │   │   │   │   ├── json-schema-async.vue
│   │   │   │   │   │   ├── json-schema-sync.vue
│   │   │   │   │   │   ├── markup-schema-async-search.vue
│   │   │   │   │   │   ├── markup-schema-async.vue
│   │   │   │   │   │   ├── markup-schema-sync.vue
│   │   │   │   │   │   ├── template-async.vue
│   │   │   │   │   │   └── template-sync.vue
│   │   │   │   │   ├── space
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── submit
│   │   │   │   │   │   ├── base.vue
│   │   │   │   │   │   └── loading.vue
│   │   │   │   │   ├── switch
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── time-picker
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   ├── transfer
│   │   │   │   │   │   ├── json-schema.vue
│   │   │   │   │   │   ├── markup-schema.vue
│   │   │   │   │   │   └── template.vue
│   │   │   │   │   └── upload
│   │   │   │   │       ├── json-schema.vue
│   │   │   │   │       ├── markup-schema.vue
│   │   │   │   │       └── template.vue
│   │   │   │   └── index.vue
│   │   │   ├── guide
│   │   │   │   ├── array-cards.md
│   │   │   │   ├── array-collapse.md
│   │   │   │   ├── array-items.md
│   │   │   │   ├── array-table.md
│   │   │   │   ├── array-tabs.md
│   │   │   │   ├── cascader.md
│   │   │   │   ├── checkbox.md
│   │   │   │   ├── date-picker.md
│   │   │   │   ├── editable.md
│   │   │   │   ├── form-button-group.md
│   │   │   │   ├── form-collapse.md
│   │   │   │   ├── form-dialog.md
│   │   │   │   ├── form-drawer.md
│   │   │   │   ├── form-grid.md
│   │   │   │   ├── form-item.md
│   │   │   │   ├── form-layout.md
│   │   │   │   ├── form-step.md
│   │   │   │   ├── form-tab.md
│   │   │   │   ├── form.md
│   │   │   │   ├── index.md
│   │   │   │   ├── input-number.md
│   │   │   │   ├── input.md
│   │   │   │   ├── password.md
│   │   │   │   ├── preview-text.md
│   │   │   │   ├── radio.md
│   │   │   │   ├── reset.md
│   │   │   │   ├── select.md
│   │   │   │   ├── space.md
│   │   │   │   ├── submit.md
│   │   │   │   ├── switch.md
│   │   │   │   ├── time-picker.md
│   │   │   │   ├── transfer.md
│   │   │   │   └── upload.md
│   │   │   └── README.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── configs
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── shared
│   │   │   │   │   ├── create-context.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── loading.ts
│   │   │   │   │   ├── portal.ts
│   │   │   │   │   ├── resolve-component.ts
│   │   │   │   │   ├── transform-component.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   └── styles
│   │   │   │       └── common.scss
│   │   │   ├── array-base
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-tabs
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── el-form
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── el-form-item
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.scss
│   │   │   │   ├── grid.scss
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── var.scss
│   │   │   ├── form-layout
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── input-number
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── space
│   │   │   │   ├── index.ts
│   │   │   │   ├── style.scss
│   │   │   │   └── style.ts
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.ts
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.ts
│   │   │       └── style.ts
│   │   ├── transformer.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── grid
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── index.ts
│   │   │   └── observer.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── json-schema
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── __snapshots__
│   │   │   │   │   └── schema.spec.ts.snap
│   │   │   │   ├── compiler.spec.ts
│   │   │   │   ├── patches.spec.ts
│   │   │   │   ├── schema.spec.ts
│   │   │   │   ├── server-validate.spec.ts
│   │   │   │   ├── shared.spec.ts
│   │   │   │   ├── transformer.spec.ts
│   │   │   │   └── traverse.spec.ts
│   │   │   ├── compiler.ts
│   │   │   ├── global.d.ts
│   │   │   ├── index.ts
│   │   │   ├── patches.ts
│   │   │   ├── polyfills
│   │   │   │   ├── index.ts
│   │   │   │   └── SPECIFICATION_1_0.ts
│   │   │   ├── schema.ts
│   │   │   ├── shared.ts
│   │   │   ├── transformer.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── next
│   │   ├── __tests__
│   │   │   ├── moment.spec.ts
│   │   │   └── sideEffects.spec.ts
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── build-style.ts
│   │   ├── create-style.ts
│   │   ├── docs
│   │   │   ├── components
│   │   │   │   ├── ArrayCards.md
│   │   │   │   ├── ArrayCards.zh-CN.md
│   │   │   │   ├── ArrayCollapse.md
│   │   │   │   ├── ArrayCollapse.zh-CN.md
│   │   │   │   ├── ArrayItems.md
│   │   │   │   ├── ArrayItems.zh-CN.md
│   │   │   │   ├── ArrayTable.md
│   │   │   │   ├── ArrayTable.zh-CN.md
│   │   │   │   ├── Cascader.md
│   │   │   │   ├── Cascader.zh-CN.md
│   │   │   │   ├── Checkbox.md
│   │   │   │   ├── Checkbox.zh-CN.md
│   │   │   │   ├── DatePicker.md
│   │   │   │   ├── DatePicker.zh-CN.md
│   │   │   │   ├── DatePicker2.md
│   │   │   │   ├── DatePicker2.zh-CN.md
│   │   │   │   ├── Editable.md
│   │   │   │   ├── Editable.zh-CN.md
│   │   │   │   ├── Form.md
│   │   │   │   ├── Form.zh-CN.md
│   │   │   │   ├── FormButtonGroup.md
│   │   │   │   ├── FormButtonGroup.zh-CN.md
│   │   │   │   ├── FormCollapse.md
│   │   │   │   ├── FormCollapse.zh-CN.md
│   │   │   │   ├── FormDialog.md
│   │   │   │   ├── FormDialog.zh-CN.md
│   │   │   │   ├── FormDrawer.md
│   │   │   │   ├── FormDrawer.zh-CN.md
│   │   │   │   ├── FormGrid.md
│   │   │   │   ├── FormGrid.zh-CN.md
│   │   │   │   ├── FormItem.md
│   │   │   │   ├── FormItem.zh-CN.md
│   │   │   │   ├── FormLayout.md
│   │   │   │   ├── FormLayout.zh-CN.md
│   │   │   │   ├── FormStep.md
│   │   │   │   ├── FormStep.zh-CN.md
│   │   │   │   ├── FormTab.md
│   │   │   │   ├── FormTab.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   ├── index.zh-CN.md
│   │   │   │   ├── Input.md
│   │   │   │   ├── Input.zh-CN.md
│   │   │   │   ├── NumberPicker.md
│   │   │   │   ├── NumberPicker.zh-CN.md
│   │   │   │   ├── Password.md
│   │   │   │   ├── Password.zh-CN.md
│   │   │   │   ├── PreviewText.md
│   │   │   │   ├── PreviewText.zh-CN.md
│   │   │   │   ├── Radio.md
│   │   │   │   ├── Radio.zh-CN.md
│   │   │   │   ├── Reset.md
│   │   │   │   ├── Reset.zh-CN.md
│   │   │   │   ├── Select.md
│   │   │   │   ├── Select.zh-CN.md
│   │   │   │   ├── SelectTable.md
│   │   │   │   ├── SelectTable.zh-CN.md
│   │   │   │   ├── Space.md
│   │   │   │   ├── Space.zh-CN.md
│   │   │   │   ├── Submit.md
│   │   │   │   ├── Submit.zh-CN.md
│   │   │   │   ├── Switch.md
│   │   │   │   ├── Switch.zh-CN.md
│   │   │   │   ├── TimePicker.md
│   │   │   │   ├── TimePicker.zh-CN.md
│   │   │   │   ├── TimePicker2.md
│   │   │   │   ├── TimePicker2.zh-CN.md
│   │   │   │   ├── Transfer.md
│   │   │   │   ├── Transfer.zh-CN.md
│   │   │   │   ├── TreeSelect.md
│   │   │   │   ├── TreeSelect.zh-CN.md
│   │   │   │   ├── Upload.md
│   │   │   │   └── Upload.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LESENCE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __builtins__
│   │   │   │   ├── empty.tsx
│   │   │   │   ├── hooks
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── useClickAway.ts
│   │   │   │   │   └── usePrefixCls.ts
│   │   │   │   ├── icons.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── loading.ts
│   │   │   │   ├── mapSize.ts
│   │   │   │   ├── mapStatus.ts
│   │   │   │   ├── moment.ts
│   │   │   │   ├── pickDataProps.ts
│   │   │   │   ├── portal.tsx
│   │   │   │   ├── render.ts
│   │   │   │   └── toArray.ts
│   │   │   ├── array-base
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-cards
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-items
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── array-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── cascader
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── checkbox
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── date-picker2
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── editable
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-button-group
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-collapse
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-dialog
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-drawer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-grid
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-item
│   │   │   │   ├── animation.scss
│   │   │   │   ├── grid.scss
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── scss
│   │   │   │   │   └── variable.scss
│   │   │   │   └── style.ts
│   │   │   ├── form-layout
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── style.ts
│   │   │   │   └── useResponsiveFormLayout.ts
│   │   │   ├── form-step
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── form-tab
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── index.ts
│   │   │   ├── input
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── main.scss
│   │   │   ├── number-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── password
│   │   │   │   ├── index.tsx
│   │   │   │   ├── PasswordStrength.tsx
│   │   │   │   └── style.ts
│   │   │   ├── preview-text
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── radio
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── reset
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── select-table
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   ├── style.ts
│   │   │   │   ├── useCheckSlackly.tsx
│   │   │   │   ├── useFilterOptions.tsx
│   │   │   │   ├── useFlatOptions.tsx
│   │   │   │   ├── useSize.tsx
│   │   │   │   ├── useTitleAddon.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── space
│   │   │   │   ├── index.tsx
│   │   │   │   ├── main.scss
│   │   │   │   └── style.ts
│   │   │   ├── style.ts
│   │   │   ├── submit
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── switch
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── time-picker2
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── transfer
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   ├── tree-select
│   │   │   │   ├── index.tsx
│   │   │   │   └── style.ts
│   │   │   └── upload
│   │   │       ├── index.tsx
│   │   │       ├── main.scss
│   │   │       ├── placeholder.ts
│   │   │       └── style.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── path
│   │   ├── .npmignore
│   │   ├── benchmark.ts
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── accessor.spec.ts
│   │   │   │   ├── basic.spec.ts
│   │   │   │   ├── match.spec.ts
│   │   │   │   ├── parser.spec.ts
│   │   │   │   └── share.spec.ts
│   │   │   ├── contexts.ts
│   │   │   ├── destructor.ts
│   │   │   ├── index.ts
│   │   │   ├── matcher.ts
│   │   │   ├── parser.ts
│   │   │   ├── shared.ts
│   │   │   ├── tokenizer.ts
│   │   │   ├── tokens.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── react
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── components
│   │   │   │   │   ├── ArrayField.md
│   │   │   │   │   ├── ArrayField.zh-CN.md
│   │   │   │   │   ├── ExpressionScope.md
│   │   │   │   │   ├── ExpressionScope.zh-CN.md
│   │   │   │   │   ├── Field.md
│   │   │   │   │   ├── Field.zh-CN.md
│   │   │   │   │   ├── FormConsumer.md
│   │   │   │   │   ├── FormConsumer.zh-CN.md
│   │   │   │   │   ├── FormProvider.md
│   │   │   │   │   ├── FormProvider.zh-CN.md
│   │   │   │   │   ├── ObjectField.md
│   │   │   │   │   ├── ObjectField.zh-CN.md
│   │   │   │   │   ├── RecordScope.md
│   │   │   │   │   ├── RecordScope.zh-CN.md
│   │   │   │   │   ├── RecordsScope.md
│   │   │   │   │   ├── RecordsScope.zh-CN.md
│   │   │   │   │   ├── RecursionField.md
│   │   │   │   │   ├── RecursionField.zh-CN.md
│   │   │   │   │   ├── SchemaField.md
│   │   │   │   │   ├── SchemaField.zh-CN.md
│   │   │   │   │   ├── VoidField.md
│   │   │   │   │   └── VoidField.zh-CN.md
│   │   │   │   ├── hooks
│   │   │   │   │   ├── useExpressionScope.md
│   │   │   │   │   ├── useExpressionScope.zh-CN.md
│   │   │   │   │   ├── useField.md
│   │   │   │   │   ├── useField.zh-CN.md
│   │   │   │   │   ├── useFieldSchema.md
│   │   │   │   │   ├── useFieldSchema.zh-CN.md
│   │   │   │   │   ├── useForm.md
│   │   │   │   │   ├── useForm.zh-CN.md
│   │   │   │   │   ├── useFormEffects.md
│   │   │   │   │   ├── useFormEffects.zh-CN.md
│   │   │   │   │   ├── useParentForm.md
│   │   │   │   │   └── useParentForm.zh-CN.md
│   │   │   │   └── shared
│   │   │   │       ├── connect.md
│   │   │   │       ├── connect.zh-CN.md
│   │   │   │       ├── context.md
│   │   │   │       ├── context.zh-CN.md
│   │   │   │       ├── mapProps.md
│   │   │   │       ├── mapProps.zh-CN.md
│   │   │   │       ├── mapReadPretty.md
│   │   │   │       ├── mapReadPretty.zh-CN.md
│   │   │   │       ├── observer.md
│   │   │   │       ├── observer.zh-CN.md
│   │   │   │       ├── Schema.md
│   │   │   │       └── Schema.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── architecture.md
│   │   │   │   ├── architecture.zh-CN.md
│   │   │   │   ├── concept.md
│   │   │   │   ├── concept.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   └── index.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── expression.spec.tsx
│   │   │   │   ├── field.spec.tsx
│   │   │   │   ├── form.spec.tsx
│   │   │   │   ├── schema.json.spec.tsx
│   │   │   │   ├── schema.markup.spec.tsx
│   │   │   │   └── shared.tsx
│   │   │   ├── components
│   │   │   │   ├── ArrayField.tsx
│   │   │   │   ├── ExpressionScope.tsx
│   │   │   │   ├── Field.tsx
│   │   │   │   ├── FormConsumer.tsx
│   │   │   │   ├── FormProvider.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── ObjectField.tsx
│   │   │   │   ├── ReactiveField.tsx
│   │   │   │   ├── RecordScope.tsx
│   │   │   │   ├── RecordsScope.tsx
│   │   │   │   ├── RecursionField.tsx
│   │   │   │   ├── SchemaField.tsx
│   │   │   │   └── VoidField.tsx
│   │   │   ├── global.d.ts
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   ├── useAttach.ts
│   │   │   │   ├── useExpressionScope.ts
│   │   │   │   ├── useField.ts
│   │   │   │   ├── useFieldSchema.ts
│   │   │   │   ├── useForm.ts
│   │   │   │   ├── useFormEffects.ts
│   │   │   │   └── useParentForm.ts
│   │   │   ├── index.ts
│   │   │   ├── shared
│   │   │   │   ├── connect.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── render.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── benchmark.ts
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── action.md
│   │   │   │   ├── action.zh-CN.md
│   │   │   │   ├── autorun.md
│   │   │   │   ├── autorun.zh-CN.md
│   │   │   │   ├── batch.md
│   │   │   │   ├── batch.zh-CN.md
│   │   │   │   ├── define.md
│   │   │   │   ├── define.zh-CN.md
│   │   │   │   ├── hasCollected.md
│   │   │   │   ├── hasCollected.zh-CN.md
│   │   │   │   ├── markObservable.md
│   │   │   │   ├── markObservable.zh-CN.md
│   │   │   │   ├── markRaw.md
│   │   │   │   ├── markRaw.zh-CN.md
│   │   │   │   ├── model.md
│   │   │   │   ├── model.zh-CN.md
│   │   │   │   ├── observable.md
│   │   │   │   ├── observable.zh-CN.md
│   │   │   │   ├── observe.md
│   │   │   │   ├── observe.zh-CN.md
│   │   │   │   ├── raw.md
│   │   │   │   ├── raw.zh-CN.md
│   │   │   │   ├── react
│   │   │   │   │   ├── observer.md
│   │   │   │   │   └── observer.zh-CN.md
│   │   │   │   ├── reaction.md
│   │   │   │   ├── reaction.zh-CN.md
│   │   │   │   ├── toJS.md
│   │   │   │   ├── toJS.zh-CN.md
│   │   │   │   ├── tracker.md
│   │   │   │   ├── tracker.zh-CN.md
│   │   │   │   ├── typeChecker.md
│   │   │   │   ├── typeChecker.zh-CN.md
│   │   │   │   ├── untracked.md
│   │   │   │   ├── untracked.zh-CN.md
│   │   │   │   └── vue
│   │   │   │       ├── observer.md
│   │   │   │       └── observer.zh-CN.md
│   │   │   ├── guide
│   │   │   │   ├── best-practice.md
│   │   │   │   ├── best-practice.zh-CN.md
│   │   │   │   ├── concept.md
│   │   │   │   ├── concept.zh-CN.md
│   │   │   │   ├── index.md
│   │   │   │   └── index.zh-CN.md
│   │   │   ├── index.md
│   │   │   └── index.zh-CN.md
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── action.spec.ts
│   │   │   │   ├── annotations.spec.ts
│   │   │   │   ├── array.spec.ts
│   │   │   │   ├── autorun.spec.ts
│   │   │   │   ├── batch.spec.ts
│   │   │   │   ├── collections-map.spec.ts
│   │   │   │   ├── collections-set.spec.ts
│   │   │   │   ├── collections-weakmap.spec.ts
│   │   │   │   ├── collections-weakset.spec.ts
│   │   │   │   ├── define.spec.ts
│   │   │   │   ├── externals.spec.ts
│   │   │   │   ├── hasCollected.spec.ts
│   │   │   │   ├── observable.spec.ts
│   │   │   │   ├── observe.spec.ts
│   │   │   │   ├── tracker.spec.ts
│   │   │   │   └── untracked.spec.ts
│   │   │   ├── action.ts
│   │   │   ├── annotations
│   │   │   │   ├── box.ts
│   │   │   │   ├── computed.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── observable.ts
│   │   │   │   ├── ref.ts
│   │   │   │   └── shallow.ts
│   │   │   ├── array.ts
│   │   │   ├── autorun.ts
│   │   │   ├── batch.ts
│   │   │   ├── checkers.ts
│   │   │   ├── environment.ts
│   │   │   ├── externals.ts
│   │   │   ├── global.d.ts
│   │   │   ├── handlers.ts
│   │   │   ├── index.ts
│   │   │   ├── internals.ts
│   │   │   ├── model.ts
│   │   │   ├── observable.ts
│   │   │   ├── observe.ts
│   │   │   ├── reaction.ts
│   │   │   ├── tracker.ts
│   │   │   ├── tree.ts
│   │   │   ├── types.ts
│   │   │   └── untracked.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive-react
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   ├── useCompatEffect.ts
│   │   │   │   ├── useCompatFactory.ts
│   │   │   │   ├── useDidUpdate.ts
│   │   │   │   ├── useForceUpdate.ts
│   │   │   │   ├── useLayoutEffect.ts
│   │   │   │   └── useObserver.ts
│   │   │   ├── index.ts
│   │   │   ├── observer.ts
│   │   │   ├── shared
│   │   │   │   ├── gc.ts
│   │   │   │   ├── global.ts
│   │   │   │   ├── immediate.ts
│   │   │   │   └── index.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── reactive-test-cases-for-react18
│   │   ├── .npmignore
│   │   ├── .umirc.js
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── index.js
│   │   │   └── MySlowList.js
│   │   ├── template.ejs
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   ├── webpack.base.ts
│   │   ├── webpack.dev.ts
│   │   └── webpack.prod.ts
│   ├── reactive-vue
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   └── observer.spec.ts
│   │   │   ├── hooks
│   │   │   │   ├── index.ts
│   │   │   │   └── useObserver.ts
│   │   │   ├── index.ts
│   │   │   ├── observer
│   │   │   │   ├── collectData.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── observerInVue2.ts
│   │   │   │   └── observerInVue3.ts
│   │   │   └── types.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── shared
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   └── index.spec.ts
│   │   │   ├── array.ts
│   │   │   ├── case.ts
│   │   │   ├── checkers.ts
│   │   │   ├── clone.ts
│   │   │   ├── compare.ts
│   │   │   ├── defaults.ts
│   │   │   ├── deprecate.ts
│   │   │   ├── global.ts
│   │   │   ├── index.ts
│   │   │   ├── instanceof.ts
│   │   │   ├── isEmpty.ts
│   │   │   ├── merge.ts
│   │   │   ├── middleware.ts
│   │   │   ├── path.ts
│   │   │   ├── string.ts
│   │   │   ├── subscribable.ts
│   │   │   └── uid.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   ├── validator
│   │   ├── .npmignore
│   │   ├── LICENSE.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── rollup.config.js
│   │   ├── src
│   │   │   ├── __tests__
│   │   │   │   ├── parser.spec.ts
│   │   │   │   ├── registry.spec.ts
│   │   │   │   └── validator.spec.ts
│   │   │   ├── formats.ts
│   │   │   ├── index.ts
│   │   │   ├── locale.ts
│   │   │   ├── parser.ts
│   │   │   ├── registry.ts
│   │   │   ├── rules.ts
│   │   │   ├── template.ts
│   │   │   ├── types.ts
│   │   │   └── validator.ts
│   │   ├── tsconfig.build.json
│   │   └── tsconfig.json
│   └── vue
│       ├── .npmignore
│       ├── bin
│       │   ├── formily-vue-fix.js
│       │   └── formily-vue-switch.js
│       ├── docs
│       │   ├── .vuepress
│       │   │   ├── components
│       │   │   │   ├── createCodeSandBox.js
│       │   │   │   ├── dumi-previewer.vue
│       │   │   │   └── highlight.js
│       │   │   ├── config.js
│       │   │   ├── enhanceApp.js
│       │   │   └── styles
│       │   │       └── index.styl
│       │   ├── api
│       │   │   ├── components
│       │   │   │   ├── array-field.md
│       │   │   │   ├── expression-scope.md
│       │   │   │   ├── field.md
│       │   │   │   ├── form-consumer.md
│       │   │   │   ├── form-provider.md
│       │   │   │   ├── object-field.md
│       │   │   │   ├── recursion-field-with-component.md
│       │   │   │   ├── recursion-field.md
│       │   │   │   ├── schema-field-with-schema.md
│       │   │   │   ├── schema-field.md
│       │   │   │   └── void-field.md
│       │   │   ├── hooks
│       │   │   │   ├── use-field-schema.md
│       │   │   │   ├── use-field.md
│       │   │   │   ├── use-form-effects.md
│       │   │   │   ├── use-form.md
│       │   │   │   └── use-parent-form.md
│       │   │   └── shared
│       │   │       ├── connect.md
│       │   │       ├── injections.md
│       │   │       ├── map-props.md
│       │   │       ├── map-read-pretty.md
│       │   │       ├── observer.md
│       │   │       └── schema.md
│       │   ├── demos
│       │   │   ├── api
│       │   │   │   ├── components
│       │   │   │   │   ├── array-field.vue
│       │   │   │   │   ├── expression-scope.vue
│       │   │   │   │   ├── field.vue
│       │   │   │   │   ├── form-consumer.vue
│       │   │   │   │   ├── form-provider.vue
│       │   │   │   │   ├── object-field.vue
│       │   │   │   │   ├── recursion-field-with-component.vue
│       │   │   │   │   ├── recursion-field.vue
│       │   │   │   │   ├── schema-field-with-schema.vue
│       │   │   │   │   ├── schema-field.vue
│       │   │   │   │   └── void-field.vue
│       │   │   │   ├── hooks
│       │   │   │   │   ├── use-field-schema.vue
│       │   │   │   │   ├── use-field.vue
│       │   │   │   │   ├── use-form-effects.vue
│       │   │   │   │   ├── use-form.vue
│       │   │   │   │   └── use-parent-form.vue
│       │   │   │   └── shared
│       │   │   │       ├── connect.vue
│       │   │   │       ├── map-props.vue
│       │   │   │       ├── map-read-pretty.vue
│       │   │   │       └── observer.vue
│       │   │   ├── index.vue
│       │   │   └── questions
│       │   │       ├── default-slot.vue
│       │   │       ├── events.vue
│       │   │       ├── named-slot.vue
│       │   │       └── scoped-slot.vue
│       │   ├── guide
│       │   │   ├── architecture.md
│       │   │   ├── concept.md
│       │   │   └── README.md
│       │   ├── questions
│       │   │   └── README.md
│       │   └── README.md
│       ├── package.json
│       ├── README.md
│       ├── rollup.config.js
│       ├── scripts
│       │   ├── postinstall.js
│       │   ├── switch-cli.js
│       │   └── utils.js
│       ├── src
│       │   ├── __tests__
│       │   │   ├── expression.scope.spec.ts
│       │   │   ├── field.spec.ts
│       │   │   ├── form.spec.ts
│       │   │   ├── schema.json.spec.ts
│       │   │   ├── schema.markup.spec.ts
│       │   │   ├── shared.spec.ts
│       │   │   └── utils.spec.ts
│       │   ├── components
│       │   │   ├── ArrayField.ts
│       │   │   ├── ExpressionScope.ts
│       │   │   ├── Field.ts
│       │   │   ├── FormConsumer.ts
│       │   │   ├── FormProvider.ts
│       │   │   ├── index.ts
│       │   │   ├── ObjectField.ts
│       │   │   ├── ReactiveField.ts
│       │   │   ├── RecursionField.ts
│       │   │   ├── SchemaField.ts
│       │   │   └── VoidField.ts
│       │   ├── global.d.ts
│       │   ├── hooks
│       │   │   ├── index.ts
│       │   │   ├── useAttach.ts
│       │   │   ├── useField.ts
│       │   │   ├── useFieldSchema.ts
│       │   │   ├── useForm.ts
│       │   │   ├── useFormEffects.ts
│       │   │   ├── useInjectionCleaner.ts
│       │   │   └── useParentForm.ts
│       │   ├── index.ts
│       │   ├── shared
│       │   │   ├── connect.ts
│       │   │   ├── context.ts
│       │   │   ├── createForm.ts
│       │   │   ├── fragment.ts
│       │   │   ├── h.ts
│       │   │   └── index.ts
│       │   ├── types
│       │   │   └── index.ts
│       │   ├── utils
│       │   │   ├── formatVNodeData.ts
│       │   │   ├── getFieldProps.ts
│       │   │   ├── getRawComponent.ts
│       │   │   └── resolveSchemaProps.ts
│       │   └── vue2-components.ts
│       ├── tsconfig.build.json
│       ├── tsconfig.json
│       └── tsconfig.types.json
├── README.md
├── README.zh-cn.md
├── scripts
│   ├── build-style
│   │   ├── buildAllStyles.ts
│   │   ├── copy.ts
│   │   ├── helper.ts
│   │   └── index.ts
│   └── rollup.base.js
├── tsconfig.build.json
├── tsconfig.jest.json
├── tsconfig.json
└── yarn.lock
```

# Files

--------------------------------------------------------------------------------
/docs/guide/scenes/edit-detail.zh-CN.md:
--------------------------------------------------------------------------------

```markdown
   1 | # 编辑详情
   2 | 
   3 | ## 编辑
   4 | 
   5 | #### Markup Schema 案例
   6 | 
   7 | ```tsx
   8 | import React, { useState, useEffect } from 'react'
   9 | import { createForm } from '@formily/core'
  10 | import { createSchemaField } from '@formily/react'
  11 | import {
  12 |   Form,
  13 |   FormItem,
  14 |   FormLayout,
  15 |   Input,
  16 |   Select,
  17 |   Cascader,
  18 |   DatePicker,
  19 |   Submit,
  20 |   FormGrid,
  21 |   Upload,
  22 |   ArrayItems,
  23 |   Editable,
  24 |   FormButtonGroup,
  25 | } from '@formily/antd'
  26 | import { action } from '@formily/reactive'
  27 | import { Card, Button, Spin } from 'antd'
  28 | import { UploadOutlined } from '@ant-design/icons'
  29 | 
  30 | const form = createForm({
  31 |   validateFirst: true,
  32 | })
  33 | 
  34 | const IDUpload = (props) => {
  35 |   return (
  36 |     <Upload
  37 |       {...props}
  38 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
  39 |       headers={{
  40 |         authorization: 'authorization-text',
  41 |       }}
  42 |     >
  43 |       <Button icon={<UploadOutlined />}>上传复印件</Button>
  44 |     </Upload>
  45 |   )
  46 | }
  47 | 
  48 | const SchemaField = createSchemaField({
  49 |   components: {
  50 |     FormItem,
  51 |     FormGrid,
  52 |     FormLayout,
  53 |     Input,
  54 |     DatePicker,
  55 |     Cascader,
  56 |     Select,
  57 |     IDUpload,
  58 |     ArrayItems,
  59 |     Editable,
  60 |   },
  61 |   scope: {
  62 |     fetchAddress: (field) => {
  63 |       const transform = (data = {}) => {
  64 |         return Object.entries(data).reduce((buf, [key, value]) => {
  65 |           if (typeof value === 'string')
  66 |             return buf.concat({
  67 |               label: value,
  68 |               value: key,
  69 |             })
  70 |           const { name, code, cities, districts } = value
  71 |           const _cities = transform(cities)
  72 |           const _districts = transform(districts)
  73 |           return buf.concat({
  74 |             label: name,
  75 |             value: code,
  76 |             children: _cities.length
  77 |               ? _cities
  78 |               : _districts.length
  79 |               ? _districts
  80 |               : undefined,
  81 |           })
  82 |         }, [])
  83 |       }
  84 | 
  85 |       field.loading = true
  86 |       fetch('//unpkg.com/china-location/dist/location.json')
  87 |         .then((res) => res.json())
  88 |         .then(
  89 |           action.bound((data) => {
  90 |             field.dataSource = transform(data)
  91 |             field.loading = false
  92 |           })
  93 |         )
  94 |     },
  95 |   },
  96 | })
  97 | 
  98 | export default () => {
  99 |   const [loading, setLoading] = useState(true)
 100 |   useEffect(() => {
 101 |     setTimeout(() => {
 102 |       form.setInitialValues({
 103 |         username: 'Aston Martin',
 104 |         firstName: 'Aston',
 105 |         lastName: 'Martin',
 106 |         email: '[email protected]',
 107 |         gender: 1,
 108 |         birthday: '1836-01-03',
 109 |         address: ['110000', '110000', '110101'],
 110 |         idCard: [
 111 |           {
 112 |             name: 'this is image',
 113 |             thumbUrl:
 114 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 115 |             uid: 'rc-upload-1615825692847-2',
 116 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 117 |           },
 118 |         ],
 119 |         contacts: [
 120 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
 121 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
 122 |         ],
 123 |       })
 124 |       setLoading(false)
 125 |     }, 2000)
 126 |   }, [])
 127 |   return (
 128 |     <div
 129 |       style={{
 130 |         display: 'flex',
 131 |         justifyContent: 'center',
 132 |         background: '#eee',
 133 |         padding: '40px 0',
 134 |       }}
 135 |     >
 136 |       <Card title="编辑用户" style={{ width: 620 }}>
 137 |         <Spin spinning={loading}>
 138 |           <Form
 139 |             form={form}
 140 |             labelCol={5}
 141 |             wrapperCol={16}
 142 |             onAutoSubmit={console.log}
 143 |           >
 144 |             <SchemaField>
 145 |               <SchemaField.String
 146 |                 name="username"
 147 |                 title="用户名"
 148 |                 required
 149 |                 x-decorator="FormItem"
 150 |                 x-component="Input"
 151 |               />
 152 |               <SchemaField.Void
 153 |                 title="姓名"
 154 |                 x-decorator="FormItem"
 155 |                 x-decorator-props={{
 156 |                   asterisk: true,
 157 |                   feedbackLayout: 'none',
 158 |                 }}
 159 |                 x-component="FormGrid"
 160 |               >
 161 |                 <SchemaField.String
 162 |                   name="firstName"
 163 |                   x-decorator="FormItem"
 164 |                   x-component="Input"
 165 |                   x-component-props={{
 166 |                     placeholder: '姓',
 167 |                   }}
 168 |                   required
 169 |                 />
 170 |                 <SchemaField.String
 171 |                   name="lastName"
 172 |                   x-decorator="FormItem"
 173 |                   x-component="Input"
 174 |                   x-component-props={{
 175 |                     placeholder: '名',
 176 |                   }}
 177 |                   required
 178 |                 />
 179 |               </SchemaField.Void>
 180 |               <SchemaField.String
 181 |                 name="email"
 182 |                 title="邮箱"
 183 |                 required
 184 |                 x-validator="email"
 185 |                 x-decorator="FormItem"
 186 |                 x-component="Input"
 187 |               />
 188 |               <SchemaField.String
 189 |                 name="gender"
 190 |                 title="性别"
 191 |                 x-decorator="FormItem"
 192 |                 x-component="Select"
 193 |                 enum={[
 194 |                   {
 195 |                     label: '男',
 196 |                     value: 1,
 197 |                   },
 198 |                   {
 199 |                     label: '女',
 200 |                     value: 2,
 201 |                   },
 202 |                   {
 203 |                     label: '第三性别',
 204 |                     value: 3,
 205 |                   },
 206 |                 ]}
 207 |                 required
 208 |               />
 209 |               <SchemaField.String
 210 |                 name="birthday"
 211 |                 title="生日"
 212 |                 required
 213 |                 x-decorator="FormItem"
 214 |                 x-component="DatePicker"
 215 |               />
 216 |               <SchemaField.String
 217 |                 name="address"
 218 |                 title="地址"
 219 |                 required
 220 |                 x-decorator="FormItem"
 221 |                 x-component="Cascader"
 222 |                 x-reactions="{{fetchAddress}}"
 223 |               />
 224 |               <SchemaField.String
 225 |                 name="idCard"
 226 |                 title="身份证复印件"
 227 |                 required
 228 |                 x-decorator="FormItem"
 229 |                 x-component="IDUpload"
 230 |               />
 231 |               <SchemaField.Array
 232 |                 name="contacts"
 233 |                 title="联系人信息"
 234 |                 required
 235 |                 x-decorator="FormItem"
 236 |                 x-component="ArrayItems"
 237 |               >
 238 |                 <SchemaField.Object x-component="ArrayItems.Item">
 239 |                   <SchemaField.Void
 240 |                     x-decorator="FormItem"
 241 |                     x-component="ArrayItems.SortHandle"
 242 |                   />
 243 |                   <SchemaField.Void
 244 |                     name="popover"
 245 |                     title="维护联系人信息"
 246 |                     x-decorator="Editable.Popover"
 247 |                     x-component="FormLayout"
 248 |                     x-component-props={{
 249 |                       layout: 'vertical',
 250 |                     }}
 251 |                     x-reactions={[
 252 |                       {
 253 |                         fulfill: {
 254 |                           schema: {
 255 |                             title: '{{$self.query(".name").value() }}',
 256 |                           },
 257 |                         },
 258 |                       },
 259 |                     ]}
 260 |                   >
 261 |                     <SchemaField.String
 262 |                       name="name"
 263 |                       required
 264 |                       title="姓名"
 265 |                       x-decorator="FormItem"
 266 |                       x-component="Input"
 267 |                       x-component-props={{
 268 |                         style: {
 269 |                           width: 300,
 270 |                         },
 271 |                       }}
 272 |                     />
 273 |                     <SchemaField.String
 274 |                       name="email"
 275 |                       title="邮箱"
 276 |                       x-validator={[{ required: true }, 'email']}
 277 |                       x-decorator="FormItem"
 278 |                       x-component="Input"
 279 |                       x-component-props={{
 280 |                         style: {
 281 |                           width: 300,
 282 |                         },
 283 |                       }}
 284 |                     />
 285 |                     <SchemaField.String
 286 |                       name="phone"
 287 |                       required
 288 |                       title="手机号"
 289 |                       x-validator="phone"
 290 |                       x-decorator="FormItem"
 291 |                       x-component="Input"
 292 |                       x-component-props={{
 293 |                         style: {
 294 |                           width: 300,
 295 |                         },
 296 |                       }}
 297 |                     />
 298 |                   </SchemaField.Void>
 299 |                   <SchemaField.Void
 300 |                     x-decorator="FormItem"
 301 |                     x-component="ArrayItems.Remove"
 302 |                   />
 303 |                 </SchemaField.Object>
 304 |                 <SchemaField.Void
 305 |                   x-component="ArrayItems.Addition"
 306 |                   title="新增联系人"
 307 |                 />
 308 |               </SchemaField.Array>
 309 |             </SchemaField>
 310 |             <FormButtonGroup.FormItem>
 311 |               <Submit block size="large">
 312 |                 提交
 313 |               </Submit>
 314 |             </FormButtonGroup.FormItem>
 315 |           </Form>
 316 |         </Spin>
 317 |       </Card>
 318 |     </div>
 319 |   )
 320 | }
 321 | ```
 322 | 
 323 | #### JSON Schema 案例
 324 | 
 325 | ```tsx
 326 | import React, { useState, useEffect } from 'react'
 327 | import { createForm } from '@formily/core'
 328 | import { createSchemaField } from '@formily/react'
 329 | import {
 330 |   Form,
 331 |   FormItem,
 332 |   FormLayout,
 333 |   Input,
 334 |   Select,
 335 |   Cascader,
 336 |   DatePicker,
 337 |   Submit,
 338 |   FormGrid,
 339 |   Upload,
 340 |   ArrayItems,
 341 |   Editable,
 342 |   FormButtonGroup,
 343 | } from '@formily/antd'
 344 | import { action } from '@formily/reactive'
 345 | import { Card, Button, Spin } from 'antd'
 346 | import { UploadOutlined } from '@ant-design/icons'
 347 | 
 348 | const form = createForm({
 349 |   validateFirst: true,
 350 | })
 351 | 
 352 | const IDUpload = (props) => {
 353 |   return (
 354 |     <Upload
 355 |       {...props}
 356 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
 357 |       headers={{
 358 |         authorization: 'authorization-text',
 359 |       }}
 360 |     >
 361 |       <Button icon={<UploadOutlined />}>上传复印件</Button>
 362 |     </Upload>
 363 |   )
 364 | }
 365 | 
 366 | const SchemaField = createSchemaField({
 367 |   components: {
 368 |     FormItem,
 369 |     FormGrid,
 370 |     FormLayout,
 371 |     Input,
 372 |     DatePicker,
 373 |     Cascader,
 374 |     Select,
 375 |     IDUpload,
 376 |     ArrayItems,
 377 |     Editable,
 378 |   },
 379 |   scope: {
 380 |     fetchAddress: (field) => {
 381 |       const transform = (data = {}) => {
 382 |         return Object.entries(data).reduce((buf, [key, value]) => {
 383 |           if (typeof value === 'string')
 384 |             return buf.concat({
 385 |               label: value,
 386 |               value: key,
 387 |             })
 388 |           const { name, code, cities, districts } = value
 389 |           const _cities = transform(cities)
 390 |           const _districts = transform(districts)
 391 |           return buf.concat({
 392 |             label: name,
 393 |             value: code,
 394 |             children: _cities.length
 395 |               ? _cities
 396 |               : _districts.length
 397 |               ? _districts
 398 |               : undefined,
 399 |           })
 400 |         }, [])
 401 |       }
 402 | 
 403 |       field.loading = true
 404 |       fetch('//unpkg.com/china-location/dist/location.json')
 405 |         .then((res) => res.json())
 406 |         .then(
 407 |           action.bound((data) => {
 408 |             field.dataSource = transform(data)
 409 |             field.loading = false
 410 |           })
 411 |         )
 412 |     },
 413 |   },
 414 | })
 415 | 
 416 | const schema = {
 417 |   type: 'object',
 418 |   properties: {
 419 |     username: {
 420 |       type: 'string',
 421 |       title: '用户名',
 422 |       required: true,
 423 |       'x-decorator': 'FormItem',
 424 |       'x-component': 'Input',
 425 |     },
 426 |     name: {
 427 |       type: 'void',
 428 |       title: '姓名',
 429 |       'x-decorator': 'FormItem',
 430 |       'x-decorator-props': {
 431 |         asterisk: true,
 432 |         feedbackLayout: 'none',
 433 |       },
 434 |       'x-component': 'FormGrid',
 435 |       properties: {
 436 |         firstName: {
 437 |           type: 'string',
 438 |           required: true,
 439 |           'x-decorator': 'FormItem',
 440 |           'x-component': 'Input',
 441 |           'x-component-props': {
 442 |             placeholder: '姓',
 443 |           },
 444 |         },
 445 |         lastName: {
 446 |           type: 'string',
 447 |           required: true,
 448 |           'x-decorator': 'FormItem',
 449 |           'x-component': 'Input',
 450 |           'x-component-props': {
 451 |             placeholder: '名',
 452 |           },
 453 |         },
 454 |       },
 455 |     },
 456 |     email: {
 457 |       type: 'string',
 458 |       title: '邮箱',
 459 |       required: true,
 460 |       'x-decorator': 'FormItem',
 461 |       'x-component': 'Input',
 462 |       'x-validator': 'email',
 463 |     },
 464 |     gender: {
 465 |       type: 'string',
 466 |       title: '性别',
 467 |       enum: [
 468 |         {
 469 |           label: '男',
 470 |           value: 1,
 471 |         },
 472 |         {
 473 |           label: '女',
 474 |           value: 2,
 475 |         },
 476 |         {
 477 |           label: '第三性别',
 478 |           value: 3,
 479 |         },
 480 |       ],
 481 |       'x-decorator': 'FormItem',
 482 |       'x-component': 'Select',
 483 |     },
 484 |     birthday: {
 485 |       type: 'string',
 486 |       required: true,
 487 |       title: '生日',
 488 |       'x-decorator': 'FormItem',
 489 |       'x-component': 'DatePicker',
 490 |     },
 491 |     address: {
 492 |       type: 'string',
 493 |       required: true,
 494 |       title: '地址',
 495 |       'x-decorator': 'FormItem',
 496 |       'x-component': 'Cascader',
 497 |       'x-reactions': '{{fetchAddress}}',
 498 |     },
 499 |     idCard: {
 500 |       type: 'string',
 501 |       required: true,
 502 |       title: '身份证复印件',
 503 |       'x-decorator': 'FormItem',
 504 |       'x-component': 'IDUpload',
 505 |     },
 506 |     contacts: {
 507 |       type: 'array',
 508 |       required: true,
 509 |       title: '联系人信息',
 510 |       'x-decorator': 'FormItem',
 511 |       'x-component': 'ArrayItems',
 512 |       items: {
 513 |         type: 'object',
 514 |         'x-component': 'ArrayItems.Item',
 515 |         properties: {
 516 |           sort: {
 517 |             type: 'void',
 518 |             'x-decorator': 'FormItem',
 519 |             'x-component': 'ArrayItems.SortHandle',
 520 |           },
 521 |           popover: {
 522 |             type: 'void',
 523 |             title: '完善联系人信息',
 524 |             'x-decorator': 'Editable.Popover',
 525 |             'x-component': 'FormLayout',
 526 |             'x-component-props': {
 527 |               layout: 'vertical',
 528 |             },
 529 |             'x-reactions': [
 530 |               {
 531 |                 fulfill: {
 532 |                   schema: {
 533 |                     title: '{{$self.query(".name").value() }}',
 534 |                   },
 535 |                 },
 536 |               },
 537 |             ],
 538 |             properties: {
 539 |               name: {
 540 |                 type: 'string',
 541 |                 title: '姓名',
 542 |                 required: true,
 543 |                 'x-decorator': 'FormItem',
 544 |                 'x-component': 'Input',
 545 |                 'x-component-props': {
 546 |                   style: {
 547 |                     width: 300,
 548 |                   },
 549 |                 },
 550 |               },
 551 |               email: {
 552 |                 type: 'string',
 553 |                 title: '邮箱',
 554 |                 'x-decorator': 'FormItem',
 555 |                 'x-component': 'Input',
 556 |                 'x-validator': [{ required: true }, 'email'],
 557 |                 'x-component-props': {
 558 |                   style: {
 559 |                     width: 300,
 560 |                   },
 561 |                 },
 562 |               },
 563 |               phone: {
 564 |                 type: 'string',
 565 |                 title: '手机号',
 566 |                 'x-decorator': 'FormItem',
 567 |                 'x-component': 'Input',
 568 |                 'x-validator': [{ required: true }, 'phone'],
 569 |                 'x-component-props': {
 570 |                   style: {
 571 |                     width: 300,
 572 |                   },
 573 |                 },
 574 |               },
 575 |             },
 576 |           },
 577 |           remove: {
 578 |             type: 'void',
 579 |             'x-decorator': 'FormItem',
 580 |             'x-component': 'ArrayItems.Remove',
 581 |           },
 582 |         },
 583 |       },
 584 |       properties: {
 585 |         addition: {
 586 |           type: 'void',
 587 |           title: '新增联系人',
 588 |           'x-component': 'ArrayItems.Addition',
 589 |         },
 590 |       },
 591 |     },
 592 |   },
 593 | }
 594 | 
 595 | export default () => {
 596 |   const [loading, setLoading] = useState(true)
 597 |   useEffect(() => {
 598 |     setTimeout(() => {
 599 |       form.setInitialValues({
 600 |         username: 'Aston Martin',
 601 |         firstName: 'Aston',
 602 |         lastName: 'Martin',
 603 |         email: '[email protected]',
 604 |         gender: 1,
 605 |         birthday: '1836-01-03',
 606 |         address: ['110000', '110000', '110101'],
 607 |         idCard: [
 608 |           {
 609 |             name: 'this is image',
 610 |             thumbUrl:
 611 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 612 |             uid: 'rc-upload-1615825692847-2',
 613 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 614 |           },
 615 |         ],
 616 |         contacts: [
 617 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
 618 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
 619 |         ],
 620 |       })
 621 |       setLoading(false)
 622 |     }, 2000)
 623 |   }, [])
 624 |   return (
 625 |     <div
 626 |       style={{
 627 |         display: 'flex',
 628 |         justifyContent: 'center',
 629 |         background: '#eee',
 630 |         padding: '40px 0',
 631 |       }}
 632 |     >
 633 |       <Card title="编辑用户" style={{ width: 620 }}>
 634 |         <Spin spinning={loading}>
 635 |           <Form
 636 |             form={form}
 637 |             labelCol={5}
 638 |             wrapperCol={16}
 639 |             onAutoSubmit={console.log}
 640 |           >
 641 |             <SchemaField schema={schema} />
 642 |             <FormButtonGroup.FormItem>
 643 |               <Submit block size="large">
 644 |                 提交
 645 |               </Submit>
 646 |             </FormButtonGroup.FormItem>
 647 |           </Form>
 648 |         </Spin>
 649 |       </Card>
 650 |     </div>
 651 |   )
 652 | }
 653 | ```
 654 | 
 655 | #### 纯 JSX 案例
 656 | 
 657 | ```tsx
 658 | import React, { useState, useEffect } from 'react'
 659 | import { createForm } from '@formily/core'
 660 | import { Field, VoidField, ArrayField } from '@formily/react'
 661 | import {
 662 |   Form,
 663 |   FormItem,
 664 |   FormLayout,
 665 |   Input,
 666 |   Select,
 667 |   Cascader,
 668 |   DatePicker,
 669 |   Submit,
 670 |   FormGrid,
 671 |   Upload,
 672 |   ArrayBase,
 673 |   Editable,
 674 |   FormButtonGroup,
 675 | } from '@formily/antd'
 676 | import { action } from '@formily/reactive'
 677 | import { Card, Button, Spin } from 'antd'
 678 | import { UploadOutlined } from '@ant-design/icons'
 679 | import './index.less'
 680 | 
 681 | const form = createForm({
 682 |   validateFirst: true,
 683 | })
 684 | 
 685 | const IDUpload = (props) => {
 686 |   return (
 687 |     <Upload
 688 |       {...props}
 689 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
 690 |       headers={{
 691 |         authorization: 'authorization-text',
 692 |       }}
 693 |     >
 694 |       <Button icon={<UploadOutlined />}>上传复印件</Button>
 695 |     </Upload>
 696 |   )
 697 | }
 698 | 
 699 | const fetchAddress = (field) => {
 700 |   const transform = (data = {}) => {
 701 |     return Object.entries(data).reduce((buf, [key, value]) => {
 702 |       if (typeof value === 'string')
 703 |         return buf.concat({
 704 |           label: value,
 705 |           value: key,
 706 |         })
 707 |       const { name, code, cities, districts } = value
 708 |       const _cities = transform(cities)
 709 |       const _districts = transform(districts)
 710 |       return buf.concat({
 711 |         label: name,
 712 |         value: code,
 713 |         children: _cities.length
 714 |           ? _cities
 715 |           : _districts.length
 716 |           ? _districts
 717 |           : undefined,
 718 |       })
 719 |     }, [])
 720 |   }
 721 | 
 722 |   field.loading = true
 723 |   fetch('//unpkg.com/china-location/dist/location.json')
 724 |     .then((res) => res.json())
 725 |     .then(
 726 |       action.bound((data) => {
 727 |         field.dataSource = transform(data)
 728 |         field.loading = false
 729 |       })
 730 |     )
 731 | }
 732 | 
 733 | export default () => {
 734 |   const [loading, setLoading] = useState(true)
 735 |   useEffect(() => {
 736 |     setTimeout(() => {
 737 |       form.setInitialValues({
 738 |         username: 'Aston Martin',
 739 |         firstName: 'Aston',
 740 |         lastName: 'Martin',
 741 |         email: '[email protected]',
 742 |         gender: 1,
 743 |         birthday: '1836-01-03',
 744 |         address: ['110000', '110000', '110101'],
 745 |         idCard: [
 746 |           {
 747 |             name: 'this is image',
 748 |             thumbUrl:
 749 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 750 |             uid: 'rc-upload-1615825692847-2',
 751 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
 752 |           },
 753 |         ],
 754 |         contacts: [
 755 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
 756 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
 757 |         ],
 758 |       })
 759 |       setLoading(false)
 760 |     }, 2000)
 761 |   }, [])
 762 |   return (
 763 |     <div
 764 |       style={{
 765 |         display: 'flex',
 766 |         justifyContent: 'center',
 767 |         background: '#eee',
 768 |         padding: '40px 0',
 769 |       }}
 770 |     >
 771 |       <Card title="编辑用户" style={{ width: 620 }}>
 772 |         <Spin spinning={loading}>
 773 |           <Form
 774 |             form={form}
 775 |             labelCol={5}
 776 |             wrapperCol={16}
 777 |             onAutoSubmit={console.log}
 778 |           >
 779 |             <Field
 780 |               name="username"
 781 |               title="用户名"
 782 |               required
 783 |               decorator={[FormItem]}
 784 |               component={[Input]}
 785 |             />
 786 |             <VoidField
 787 |               name="name"
 788 |               title="姓名"
 789 |               decorator={[
 790 |                 FormItem,
 791 |                 {
 792 |                   asterisk: true,
 793 |                   feedbackLayout: 'none',
 794 |                 },
 795 |               ]}
 796 |               component={[FormGrid]}
 797 |             >
 798 |               <Field
 799 |                 name="firstName"
 800 |                 decorator={[FormItem]}
 801 |                 component={[
 802 |                   Input,
 803 |                   {
 804 |                     placeholder: '姓',
 805 |                   },
 806 |                 ]}
 807 |                 required
 808 |               />
 809 |               <Field
 810 |                 name="lastName"
 811 |                 decorator={[FormItem]}
 812 |                 component={[
 813 |                   Input,
 814 |                   {
 815 |                     placeholder: '名',
 816 |                   },
 817 |                 ]}
 818 |                 required
 819 |               />
 820 |             </VoidField>
 821 |             <Field
 822 |               name="email"
 823 |               title="邮箱"
 824 |               required
 825 |               validator="email"
 826 |               decorator={[FormItem]}
 827 |               component={[Input]}
 828 |             />
 829 |             <Field
 830 |               name="gender"
 831 |               title="性别"
 832 |               decorator={[FormItem]}
 833 |               component={[Select]}
 834 |               dataSource={[
 835 |                 {
 836 |                   label: '男',
 837 |                   value: 1,
 838 |                 },
 839 |                 {
 840 |                   label: '女',
 841 |                   value: 2,
 842 |                 },
 843 |                 {
 844 |                   label: '第三性别',
 845 |                   value: 3,
 846 |                 },
 847 |               ]}
 848 |               required
 849 |             />
 850 |             <Field
 851 |               name="birthday"
 852 |               title="生日"
 853 |               required
 854 |               decorator={[FormItem]}
 855 |               component={[DatePicker]}
 856 |             />
 857 |             <Field
 858 |               name="address"
 859 |               title="地址"
 860 |               required
 861 |               decorator={[FormItem]}
 862 |               component={[Cascader]}
 863 |               reactions={fetchAddress}
 864 |             />
 865 |             <Field
 866 |               name="idCard"
 867 |               title="身份证复印件"
 868 |               required
 869 |               decorator={[FormItem]}
 870 |               component={[IDUpload]}
 871 |             />
 872 |             <ArrayField
 873 |               name="contacts"
 874 |               title="联系人信息"
 875 |               decorator={[FormItem]}
 876 |             >
 877 |               {(field) => (
 878 |                 <ArrayBase>
 879 |                   {field.value?.map((item, index) => (
 880 |                     <div key={index} className="array-items-item">
 881 |                       <Field
 882 |                         name={`${index}`}
 883 |                         title="完善联系人信息"
 884 |                         component={[Editable.Popover]}
 885 |                         reactions={(field) => {
 886 |                           field.title =
 887 |                             field.query('.[].name').value() || field.title
 888 |                         }}
 889 |                       >
 890 |                         <VoidField
 891 |                           name="layout"
 892 |                           component={[FormLayout, { layout: 'vertical' }]}
 893 |                         >
 894 |                           <Field
 895 |                             name="name"
 896 |                             title="姓名"
 897 |                             required
 898 |                             decorator={[FormItem]}
 899 |                             component={[
 900 |                               Input,
 901 |                               {
 902 |                                 style: {
 903 |                                   width: 300,
 904 |                                 },
 905 |                               },
 906 |                             ]}
 907 |                           />
 908 |                           <Field
 909 |                             name="email"
 910 |                             title="邮箱"
 911 |                             required
 912 |                             validator="email"
 913 |                             decorator={[FormItem]}
 914 |                             component={[
 915 |                               Input,
 916 |                               {
 917 |                                 style: {
 918 |                                   width: 300,
 919 |                                 },
 920 |                               },
 921 |                             ]}
 922 |                           />
 923 |                           <Field
 924 |                             name="phone"
 925 |                             title="手机号"
 926 |                             required
 927 |                             validator="phone"
 928 |                             decorator={[FormItem]}
 929 |                             component={[
 930 |                               Input,
 931 |                               {
 932 |                                 style: {
 933 |                                   width: 300,
 934 |                                 },
 935 |                               },
 936 |                             ]}
 937 |                           />
 938 |                         </VoidField>
 939 |                       </Field>
 940 |                       <FormItem.BaseItem>
 941 |                         <ArrayBase.Remove index={index} />
 942 |                         <ArrayBase.MoveDown index={index} />
 943 |                         <ArrayBase.MoveUp index={index} />
 944 |                       </FormItem.BaseItem>
 945 |                     </div>
 946 |                   ))}
 947 |                   <ArrayBase.Addition title="新增联系人" />
 948 |                 </ArrayBase>
 949 |               )}
 950 |             </ArrayField>
 951 |             <FormButtonGroup.FormItem>
 952 |               <Submit block size="large">
 953 |                 提交
 954 |               </Submit>
 955 |             </FormButtonGroup.FormItem>
 956 |           </Form>
 957 |         </Spin>
 958 |       </Card>
 959 |     </div>
 960 |   )
 961 | }
 962 | ```
 963 | 
 964 | ## 详情
 965 | 
 966 | #### Markup Schema 案例
 967 | 
 968 | ```tsx
 969 | import React, { useState, useEffect } from 'react'
 970 | import { createForm } from '@formily/core'
 971 | import { createSchemaField, useField } from '@formily/react'
 972 | import {
 973 |   Form,
 974 |   FormItem,
 975 |   FormLayout,
 976 |   Input,
 977 |   Select,
 978 |   Cascader,
 979 |   DatePicker,
 980 |   FormGrid,
 981 |   Upload,
 982 |   ArrayItems,
 983 |   Editable,
 984 |   PreviewText,
 985 | } from '@formily/antd'
 986 | import { action } from '@formily/reactive'
 987 | import { Card, Button, Spin } from 'antd'
 988 | import { UploadOutlined } from '@ant-design/icons'
 989 | 
 990 | const form = createForm({
 991 |   readPretty: true,
 992 |   validateFirst: true,
 993 | })
 994 | 
 995 | const IDUpload = (props) => {
 996 |   const field = useField()
 997 |   return (
 998 |     <Upload
 999 |       {...props}
1000 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
1001 |       headers={{
1002 |         authorization: 'authorization-text',
1003 |       }}
1004 |     >
1005 |       {field.editable && <Button icon={<UploadOutlined />}>上传复印件</Button>}
1006 |     </Upload>
1007 |   )
1008 | }
1009 | 
1010 | const SchemaField = createSchemaField({
1011 |   components: {
1012 |     FormItem,
1013 |     FormGrid,
1014 |     FormLayout,
1015 |     Input,
1016 |     DatePicker,
1017 |     Cascader,
1018 |     Select,
1019 |     IDUpload,
1020 |     ArrayItems,
1021 |     Editable,
1022 |   },
1023 |   scope: {
1024 |     fetchAddress: (field) => {
1025 |       const transform = (data = {}) => {
1026 |         return Object.entries(data).reduce((buf, [key, value]) => {
1027 |           if (typeof value === 'string')
1028 |             return buf.concat({
1029 |               label: value,
1030 |               value: key,
1031 |             })
1032 |           const { name, code, cities, districts } = value
1033 |           const _cities = transform(cities)
1034 |           const _districts = transform(districts)
1035 |           return buf.concat({
1036 |             label: name,
1037 |             value: code,
1038 |             children: _cities.length
1039 |               ? _cities
1040 |               : _districts.length
1041 |               ? _districts
1042 |               : undefined,
1043 |           })
1044 |         }, [])
1045 |       }
1046 | 
1047 |       field.loading = true
1048 |       fetch('//unpkg.com/china-location/dist/location.json')
1049 |         .then((res) => res.json())
1050 |         .then(
1051 |           action.bound((data) => {
1052 |             field.dataSource = transform(data)
1053 |             field.loading = false
1054 |           })
1055 |         )
1056 |     },
1057 |   },
1058 | })
1059 | 
1060 | export default () => {
1061 |   const [loading, setLoading] = useState(true)
1062 |   useEffect(() => {
1063 |     setTimeout(() => {
1064 |       form.setInitialValues({
1065 |         username: 'Aston Martin',
1066 |         firstName: 'Aston',
1067 |         lastName: 'Martin',
1068 |         email: '[email protected]',
1069 |         gender: 1,
1070 |         birthday: '1836-01-03',
1071 |         address: ['110000', '110000', '110101'],
1072 |         idCard: [
1073 |           {
1074 |             name: 'this is image',
1075 |             thumbUrl:
1076 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1077 |             uid: 'rc-upload-1615825692847-2',
1078 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1079 |           },
1080 |         ],
1081 |         contacts: [
1082 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
1083 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
1084 |         ],
1085 |       })
1086 |       setLoading(false)
1087 |     }, 2000)
1088 |   }, [])
1089 |   return (
1090 |     <div
1091 |       style={{
1092 |         display: 'flex',
1093 |         justifyContent: 'center',
1094 |         background: '#eee',
1095 |         padding: '40px 0',
1096 |       }}
1097 |     >
1098 |       <PreviewText.Placeholder value="-">
1099 |         <Card title="用户详情" style={{ width: 620 }}>
1100 |           <Spin spinning={loading}>
1101 |             <Form
1102 |               form={form}
1103 |               labelCol={5}
1104 |               wrapperCol={16}
1105 |               onAutoSubmit={console.log}
1106 |             >
1107 |               <SchemaField>
1108 |                 <SchemaField.String
1109 |                   name="username"
1110 |                   title="用户名"
1111 |                   required
1112 |                   x-decorator="FormItem"
1113 |                   x-component="Input"
1114 |                 />
1115 |                 <SchemaField.Void
1116 |                   title="姓名"
1117 |                   x-decorator="FormItem"
1118 |                   x-decorator-props={{
1119 |                     feedbackLayout: 'none',
1120 |                   }}
1121 |                   x-component="FormGrid"
1122 |                 >
1123 |                   <SchemaField.String
1124 |                     name="firstName"
1125 |                     x-decorator="FormItem"
1126 |                     x-component="Input"
1127 |                     x-component-props={{
1128 |                       placeholder: '姓',
1129 |                     }}
1130 |                     required
1131 |                   />
1132 |                   <SchemaField.String
1133 |                     name="lastName"
1134 |                     x-decorator="FormItem"
1135 |                     x-component="Input"
1136 |                     x-component-props={{
1137 |                       placeholder: '名',
1138 |                     }}
1139 |                     required
1140 |                   />
1141 |                 </SchemaField.Void>
1142 |                 <SchemaField.String
1143 |                   name="email"
1144 |                   title="邮箱"
1145 |                   required
1146 |                   x-validator="email"
1147 |                   x-decorator="FormItem"
1148 |                   x-component="Input"
1149 |                 />
1150 |                 <SchemaField.String
1151 |                   name="gender"
1152 |                   title="性别"
1153 |                   x-decorator="FormItem"
1154 |                   x-component="Select"
1155 |                   enum={[
1156 |                     {
1157 |                       label: '男',
1158 |                       value: 1,
1159 |                     },
1160 |                     {
1161 |                       label: '女',
1162 |                       value: 2,
1163 |                     },
1164 |                     {
1165 |                       label: '第三性别',
1166 |                       value: 3,
1167 |                     },
1168 |                   ]}
1169 |                   required
1170 |                 />
1171 |                 <SchemaField.String
1172 |                   name="birthday"
1173 |                   title="生日"
1174 |                   required
1175 |                   x-decorator="FormItem"
1176 |                   x-component="DatePicker"
1177 |                 />
1178 |                 <SchemaField.String
1179 |                   name="address"
1180 |                   title="地址"
1181 |                   required
1182 |                   x-decorator="FormItem"
1183 |                   x-component="Cascader"
1184 |                   x-reactions="{{fetchAddress}}"
1185 |                 />
1186 |                 <SchemaField.String
1187 |                   name="idCard"
1188 |                   title="身份证复印件"
1189 |                   required
1190 |                   x-decorator="FormItem"
1191 |                   x-component="IDUpload"
1192 |                 />
1193 |                 <SchemaField.Array
1194 |                   name="contacts"
1195 |                   title="联系人信息"
1196 |                   required
1197 |                   x-decorator="FormItem"
1198 |                   x-component="ArrayItems"
1199 |                 >
1200 |                   <SchemaField.Object x-component="ArrayItems.Item">
1201 |                     <SchemaField.Void
1202 |                       x-decorator="FormItem"
1203 |                       x-component="ArrayItems.SortHandle"
1204 |                     />
1205 |                     <SchemaField.Void
1206 |                       name="popover"
1207 |                       title="维护联系人信息"
1208 |                       x-decorator="Editable.Popover"
1209 |                       x-component="FormLayout"
1210 |                       x-component-props={{
1211 |                         layout: 'vertical',
1212 |                       }}
1213 |                       x-reactions={[
1214 |                         {
1215 |                           fulfill: {
1216 |                             schema: {
1217 |                               title: '{{$self.query(".name").value() }}',
1218 |                             },
1219 |                           },
1220 |                         },
1221 |                       ]}
1222 |                     >
1223 |                       <SchemaField.String
1224 |                         name="name"
1225 |                         required
1226 |                         title="姓名"
1227 |                         x-decorator="FormItem"
1228 |                         x-component="Input"
1229 |                         x-component-props={{
1230 |                           style: {
1231 |                             width: 300,
1232 |                           },
1233 |                         }}
1234 |                       />
1235 |                       <SchemaField.String
1236 |                         name="email"
1237 |                         title="邮箱"
1238 |                         x-validator={[{ required: true }, 'email']}
1239 |                         x-decorator="FormItem"
1240 |                         x-component="Input"
1241 |                         x-component-props={{
1242 |                           style: {
1243 |                             width: 300,
1244 |                           },
1245 |                         }}
1246 |                       />
1247 |                       <SchemaField.String
1248 |                         name="phone"
1249 |                         required
1250 |                         title="手机号"
1251 |                         x-validator="phone"
1252 |                         x-decorator="FormItem"
1253 |                         x-component="Input"
1254 |                         x-component-props={{
1255 |                           style: {
1256 |                             width: 300,
1257 |                           },
1258 |                         }}
1259 |                       />
1260 |                     </SchemaField.Void>
1261 |                     <SchemaField.Void
1262 |                       x-decorator="FormItem"
1263 |                       x-component="ArrayItems.Remove"
1264 |                     />
1265 |                   </SchemaField.Object>
1266 |                   <SchemaField.Void
1267 |                     x-component="ArrayItems.Addition"
1268 |                     title="新增联系人"
1269 |                   />
1270 |                 </SchemaField.Array>
1271 |               </SchemaField>
1272 |             </Form>
1273 |           </Spin>
1274 |         </Card>
1275 |       </PreviewText.Placeholder>
1276 |     </div>
1277 |   )
1278 | }
1279 | ```
1280 | 
1281 | #### JSON Schema 案例
1282 | 
1283 | ```tsx
1284 | import React, { useState, useEffect } from 'react'
1285 | import { createForm } from '@formily/core'
1286 | import { createSchemaField, useField } from '@formily/react'
1287 | import {
1288 |   Form,
1289 |   FormItem,
1290 |   FormLayout,
1291 |   Input,
1292 |   Select,
1293 |   Cascader,
1294 |   DatePicker,
1295 |   FormGrid,
1296 |   Upload,
1297 |   ArrayItems,
1298 |   Editable,
1299 |   PreviewText,
1300 | } from '@formily/antd'
1301 | import { action } from '@formily/reactive'
1302 | import { Card, Button, Spin } from 'antd'
1303 | import { UploadOutlined } from '@ant-design/icons'
1304 | 
1305 | const form = createForm({
1306 |   readPretty: true,
1307 |   validateFirst: true,
1308 | })
1309 | 
1310 | const IDUpload = (props) => {
1311 |   const field = useField()
1312 |   return (
1313 |     <Upload
1314 |       {...props}
1315 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
1316 |       headers={{
1317 |         authorization: 'authorization-text',
1318 |       }}
1319 |     >
1320 |       {field.editable && <Button icon={<UploadOutlined />}>上传复印件</Button>}
1321 |     </Upload>
1322 |   )
1323 | }
1324 | 
1325 | const SchemaField = createSchemaField({
1326 |   components: {
1327 |     FormItem,
1328 |     FormGrid,
1329 |     FormLayout,
1330 |     Input,
1331 |     DatePicker,
1332 |     Cascader,
1333 |     Select,
1334 |     IDUpload,
1335 |     ArrayItems,
1336 |     Editable,
1337 |   },
1338 |   scope: {
1339 |     fetchAddress: (field) => {
1340 |       const transform = (data = {}) => {
1341 |         return Object.entries(data).reduce((buf, [key, value]) => {
1342 |           if (typeof value === 'string')
1343 |             return buf.concat({
1344 |               label: value,
1345 |               value: key,
1346 |             })
1347 |           const { name, code, cities, districts } = value
1348 |           const _cities = transform(cities)
1349 |           const _districts = transform(districts)
1350 |           return buf.concat({
1351 |             label: name,
1352 |             value: code,
1353 |             children: _cities.length
1354 |               ? _cities
1355 |               : _districts.length
1356 |               ? _districts
1357 |               : undefined,
1358 |           })
1359 |         }, [])
1360 |       }
1361 | 
1362 |       field.loading = true
1363 |       fetch('//unpkg.com/china-location/dist/location.json')
1364 |         .then((res) => res.json())
1365 |         .then(
1366 |           action.bound((data) => {
1367 |             field.dataSource = transform(data)
1368 |             field.loading = false
1369 |           })
1370 |         )
1371 |     },
1372 |   },
1373 | })
1374 | 
1375 | const schema = {
1376 |   type: 'object',
1377 |   properties: {
1378 |     username: {
1379 |       type: 'string',
1380 |       title: '用户名',
1381 |       required: true,
1382 |       'x-decorator': 'FormItem',
1383 |       'x-component': 'Input',
1384 |     },
1385 |     name: {
1386 |       type: 'void',
1387 |       title: '姓名',
1388 |       'x-decorator': 'FormItem',
1389 |       'x-decorator-props': {
1390 |         asterisk: true,
1391 |         feedbackLayout: 'none',
1392 |       },
1393 |       'x-component': 'FormGrid',
1394 |       properties: {
1395 |         firstName: {
1396 |           type: 'string',
1397 |           required: true,
1398 |           'x-decorator': 'FormItem',
1399 |           'x-component': 'Input',
1400 |           'x-component-props': {
1401 |             placeholder: '姓',
1402 |           },
1403 |         },
1404 |         lastName: {
1405 |           type: 'string',
1406 |           required: true,
1407 |           'x-decorator': 'FormItem',
1408 |           'x-component': 'Input',
1409 |           'x-component-props': {
1410 |             placeholder: '名',
1411 |           },
1412 |         },
1413 |       },
1414 |     },
1415 |     email: {
1416 |       type: 'string',
1417 |       title: '邮箱',
1418 |       required: true,
1419 |       'x-decorator': 'FormItem',
1420 |       'x-component': 'Input',
1421 |       'x-validator': 'email',
1422 |     },
1423 |     gender: {
1424 |       type: 'string',
1425 |       title: '性别',
1426 |       enum: [
1427 |         {
1428 |           label: '男',
1429 |           value: 1,
1430 |         },
1431 |         {
1432 |           label: '女',
1433 |           value: 2,
1434 |         },
1435 |         {
1436 |           label: '第三性别',
1437 |           value: 3,
1438 |         },
1439 |       ],
1440 |       'x-decorator': 'FormItem',
1441 |       'x-component': 'Select',
1442 |     },
1443 |     birthday: {
1444 |       type: 'string',
1445 |       required: true,
1446 |       title: '生日',
1447 |       'x-decorator': 'FormItem',
1448 |       'x-component': 'DatePicker',
1449 |     },
1450 |     address: {
1451 |       type: 'string',
1452 |       required: true,
1453 |       title: '地址',
1454 |       'x-decorator': 'FormItem',
1455 |       'x-component': 'Cascader',
1456 |       'x-reactions': '{{fetchAddress}}',
1457 |     },
1458 |     idCard: {
1459 |       type: 'string',
1460 |       required: true,
1461 |       title: '身份证复印件',
1462 |       'x-decorator': 'FormItem',
1463 |       'x-component': 'IDUpload',
1464 |     },
1465 |     contacts: {
1466 |       type: 'array',
1467 |       required: true,
1468 |       title: '联系人信息',
1469 |       'x-decorator': 'FormItem',
1470 |       'x-component': 'ArrayItems',
1471 |       items: {
1472 |         type: 'object',
1473 |         'x-component': 'ArrayItems.Item',
1474 |         properties: {
1475 |           sort: {
1476 |             type: 'void',
1477 |             'x-decorator': 'FormItem',
1478 |             'x-component': 'ArrayItems.SortHandle',
1479 |           },
1480 |           popover: {
1481 |             type: 'void',
1482 |             title: '完善联系人信息',
1483 |             'x-decorator': 'Editable.Popover',
1484 |             'x-component': 'FormLayout',
1485 |             'x-component-props': {
1486 |               layout: 'vertical',
1487 |             },
1488 |             'x-reactions': [
1489 |               {
1490 |                 fulfill: {
1491 |                   schema: {
1492 |                     title: '{{$self.query(".name").value() }}',
1493 |                   },
1494 |                 },
1495 |               },
1496 |             ],
1497 |             properties: {
1498 |               name: {
1499 |                 type: 'string',
1500 |                 title: '姓名',
1501 |                 required: true,
1502 |                 'x-decorator': 'FormItem',
1503 |                 'x-component': 'Input',
1504 |                 'x-component-props': {
1505 |                   style: {
1506 |                     width: 300,
1507 |                   },
1508 |                 },
1509 |               },
1510 |               email: {
1511 |                 type: 'string',
1512 |                 title: '邮箱',
1513 |                 'x-decorator': 'FormItem',
1514 |                 'x-component': 'Input',
1515 |                 'x-validator': [{ required: true }, 'email'],
1516 |                 'x-component-props': {
1517 |                   style: {
1518 |                     width: 300,
1519 |                   },
1520 |                 },
1521 |               },
1522 |               phone: {
1523 |                 type: 'string',
1524 |                 title: '手机号',
1525 |                 'x-decorator': 'FormItem',
1526 |                 'x-component': 'Input',
1527 |                 'x-validator': [{ required: true }, 'phone'],
1528 |                 'x-component-props': {
1529 |                   style: {
1530 |                     width: 300,
1531 |                   },
1532 |                 },
1533 |               },
1534 |             },
1535 |           },
1536 |           remove: {
1537 |             type: 'void',
1538 |             'x-decorator': 'FormItem',
1539 |             'x-component': 'ArrayItems.Remove',
1540 |           },
1541 |         },
1542 |       },
1543 |       properties: {
1544 |         addition: {
1545 |           type: 'void',
1546 |           title: '新增联系人',
1547 |           'x-component': 'ArrayItems.Addition',
1548 |         },
1549 |       },
1550 |     },
1551 |   },
1552 | }
1553 | 
1554 | export default () => {
1555 |   const [loading, setLoading] = useState(true)
1556 |   useEffect(() => {
1557 |     setTimeout(() => {
1558 |       form.setInitialValues({
1559 |         username: 'Aston Martin',
1560 |         firstName: 'Aston',
1561 |         lastName: 'Martin',
1562 |         email: '[email protected]',
1563 |         gender: 1,
1564 |         birthday: '1836-01-03',
1565 |         address: ['110000', '110000', '110101'],
1566 |         idCard: [
1567 |           {
1568 |             name: 'this is image',
1569 |             thumbUrl:
1570 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1571 |             uid: 'rc-upload-1615825692847-2',
1572 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1573 |           },
1574 |         ],
1575 |         contacts: [
1576 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
1577 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
1578 |         ],
1579 |       })
1580 |       setLoading(false)
1581 |     }, 2000)
1582 |   }, [])
1583 |   return (
1584 |     <div
1585 |       style={{
1586 |         display: 'flex',
1587 |         justifyContent: 'center',
1588 |         background: '#eee',
1589 |         padding: '40px 0',
1590 |       }}
1591 |     >
1592 |       <PreviewText.Placeholder value="-">
1593 |         <Card title="用户详情" style={{ width: 620 }}>
1594 |           <Spin spinning={loading}>
1595 |             <Form
1596 |               form={form}
1597 |               labelCol={5}
1598 |               wrapperCol={16}
1599 |               onAutoSubmit={console.log}
1600 |             >
1601 |               <SchemaField schema={schema} />
1602 |             </Form>
1603 |           </Spin>
1604 |         </Card>
1605 |       </PreviewText.Placeholder>
1606 |     </div>
1607 |   )
1608 | }
1609 | ```
1610 | 
1611 | #### 纯 JSX 案例
1612 | 
1613 | ```tsx
1614 | import React, { useState, useEffect } from 'react'
1615 | import { createForm } from '@formily/core'
1616 | import { Field, VoidField, ArrayField, useField } from '@formily/react'
1617 | import {
1618 |   Form,
1619 |   FormItem,
1620 |   FormLayout,
1621 |   Input,
1622 |   Select,
1623 |   Cascader,
1624 |   DatePicker,
1625 |   FormGrid,
1626 |   ArrayBase,
1627 |   Upload,
1628 |   PreviewText,
1629 |   Editable,
1630 | } from '@formily/antd'
1631 | import { action } from '@formily/reactive'
1632 | import { Card, Button, Spin } from 'antd'
1633 | import { UploadOutlined } from '@ant-design/icons'
1634 | import './index.less'
1635 | 
1636 | const form = createForm({
1637 |   validateFirst: true,
1638 |   readPretty: true,
1639 | })
1640 | 
1641 | const IDUpload = (props) => {
1642 |   const field = useField()
1643 |   return (
1644 |     <Upload
1645 |       {...props}
1646 |       action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
1647 |       headers={{
1648 |         authorization: 'authorization-text',
1649 |       }}
1650 |     >
1651 |       {field.editable && <Button icon={<UploadOutlined />}>上传复印件</Button>}
1652 |     </Upload>
1653 |   )
1654 | }
1655 | 
1656 | const fetchAddress = (field) => {
1657 |   const transform = (data = {}) => {
1658 |     return Object.entries(data).reduce((buf, [key, value]) => {
1659 |       if (typeof value === 'string')
1660 |         return buf.concat({
1661 |           label: value,
1662 |           value: key,
1663 |         })
1664 |       const { name, code, cities, districts } = value
1665 |       const _cities = transform(cities)
1666 |       const _districts = transform(districts)
1667 |       return buf.concat({
1668 |         label: name,
1669 |         value: code,
1670 |         children: _cities.length
1671 |           ? _cities
1672 |           : _districts.length
1673 |           ? _districts
1674 |           : undefined,
1675 |       })
1676 |     }, [])
1677 |   }
1678 | 
1679 |   field.loading = true
1680 |   fetch('//unpkg.com/china-location/dist/location.json')
1681 |     .then((res) => res.json())
1682 |     .then(
1683 |       action.bound((data) => {
1684 |         field.dataSource = transform(data)
1685 |         field.loading = false
1686 |       })
1687 |     )
1688 | }
1689 | 
1690 | export default () => {
1691 |   const [loading, setLoading] = useState(true)
1692 |   useEffect(() => {
1693 |     setTimeout(() => {
1694 |       form.setInitialValues({
1695 |         username: 'Aston Martin',
1696 |         firstName: 'Aston',
1697 |         lastName: 'Martin',
1698 |         email: '[email protected]',
1699 |         gender: 1,
1700 |         birthday: '1836-01-03',
1701 |         address: ['110000', '110000', '110101'],
1702 |         idCard: [
1703 |           {
1704 |             name: 'this is image',
1705 |             thumbUrl:
1706 |               'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1707 |             uid: 'rc-upload-1615825692847-2',
1708 |             url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
1709 |           },
1710 |         ],
1711 |         contacts: [
1712 |           { name: '张三', phone: '13245633378', email: '[email protected]' },
1713 |           { name: '李四', phone: '16873452678', email: '[email protected]' },
1714 |         ],
1715 |       })
1716 |       setLoading(false)
1717 |     }, 2000)
1718 |   }, [])
1719 |   return (
1720 |     <div
1721 |       style={{
1722 |         display: 'flex',
1723 |         justifyContent: 'center',
1724 |         background: '#eee',
1725 |         padding: '40px 0',
1726 |       }}
1727 |     >
1728 |       <PreviewText.Placeholder value="-">
1729 |         <Card title="编辑用户" style={{ width: 620 }}>
1730 |           <Spin spinning={loading}>
1731 |             <Form
1732 |               form={form}
1733 |               labelCol={5}
1734 |               wrapperCol={16}
1735 |               onAutoSubmit={console.log}
1736 |             >
1737 |               <Field
1738 |                 name="username"
1739 |                 title="用户名"
1740 |                 required
1741 |                 decorator={[FormItem]}
1742 |                 component={[Input]}
1743 |               />
1744 |               <VoidField
1745 |                 name="name"
1746 |                 title="姓名"
1747 |                 decorator={[
1748 |                   FormItem,
1749 |                   {
1750 |                     feedbackLayout: 'none',
1751 |                   },
1752 |                 ]}
1753 |                 component={[FormGrid]}
1754 |               >
1755 |                 <Field
1756 |                   name="firstName"
1757 |                   decorator={[FormItem]}
1758 |                   component={[
1759 |                     Input,
1760 |                     {
1761 |                       placeholder: '姓',
1762 |                     },
1763 |                   ]}
1764 |                   required
1765 |                 />
1766 |                 <Field
1767 |                   name="lastName"
1768 |                   decorator={[FormItem]}
1769 |                   component={[
1770 |                     Input,
1771 |                     {
1772 |                       placeholder: '名',
1773 |                     },
1774 |                   ]}
1775 |                   required
1776 |                 />
1777 |               </VoidField>
1778 |               <Field
1779 |                 name="email"
1780 |                 title="邮箱"
1781 |                 required
1782 |                 validator="email"
1783 |                 decorator={[FormItem]}
1784 |                 component={[Input]}
1785 |               />
1786 |               <Field
1787 |                 name="gender"
1788 |                 title="性别"
1789 |                 decorator={[FormItem]}
1790 |                 component={[Select]}
1791 |                 dataSource={[
1792 |                   {
1793 |                     label: '男',
1794 |                     value: 1,
1795 |                   },
1796 |                   {
1797 |                     label: '女',
1798 |                     value: 2,
1799 |                   },
1800 |                   {
1801 |                     label: '第三性别',
1802 |                     value: 3,
1803 |                   },
1804 |                 ]}
1805 |                 required
1806 |               />
1807 |               <Field
1808 |                 name="birthday"
1809 |                 title="生日"
1810 |                 required
1811 |                 decorator={[FormItem]}
1812 |                 component={[DatePicker]}
1813 |               />
1814 |               <Field
1815 |                 name="address"
1816 |                 title="地址"
1817 |                 required
1818 |                 decorator={[FormItem]}
1819 |                 component={[Cascader]}
1820 |                 reactions={fetchAddress}
1821 |               />
1822 |               <Field
1823 |                 name="idCard"
1824 |                 title="身份证复印件"
1825 |                 required
1826 |                 decorator={[FormItem]}
1827 |                 component={[IDUpload]}
1828 |               />
1829 |               <ArrayField
1830 |                 name="contacts"
1831 |                 title="联系人信息"
1832 |                 decorator={[FormItem]}
1833 |               >
1834 |                 {(field) => (
1835 |                   <ArrayBase>
1836 |                     {field.value?.map((item, index) => (
1837 |                       <div key={index} className="array-items-item">
1838 |                         <Field
1839 |                           name={`${index}`}
1840 |                           title="完善联系人信息"
1841 |                           component={[Editable.Popover]}
1842 |                           reactions={(field) => {
1843 |                             field.title =
1844 |                               field.query('.[].name').value() || field.title
1845 |                           }}
1846 |                         >
1847 |                           <VoidField
1848 |                             name="layout"
1849 |                             component={[FormLayout, { layout: 'vertical' }]}
1850 |                           >
1851 |                             <Field
1852 |                               name="name"
1853 |                               title="姓名"
1854 |                               required
1855 |                               decorator={[FormItem]}
1856 |                               component={[
1857 |                                 Input,
1858 |                                 {
1859 |                                   style: {
1860 |                                     width: 300,
1861 |                                   },
1862 |                                 },
1863 |                               ]}
1864 |                             />
1865 |                             <Field
1866 |                               name="email"
1867 |                               title="邮箱"
1868 |                               required
1869 |                               validator="email"
1870 |                               decorator={[FormItem]}
1871 |                               component={[
1872 |                                 Input,
1873 |                                 {
1874 |                                   style: {
1875 |                                     width: 300,
1876 |                                   },
1877 |                                 },
1878 |                               ]}
1879 |                             />
1880 |                             <Field
1881 |                               name="phone"
1882 |                               title="手机号"
1883 |                               required
1884 |                               validator="phone"
1885 |                               decorator={[FormItem]}
1886 |                               component={[
1887 |                                 Input,
1888 |                                 {
1889 |                                   style: {
1890 |                                     width: 300,
1891 |                                   },
1892 |                                 },
1893 |                               ]}
1894 |                             />
1895 |                           </VoidField>
1896 |                         </Field>
1897 |                       </div>
1898 |                     ))}
1899 |                     <ArrayBase.Addition title="新增联系人" />
1900 |                   </ArrayBase>
1901 |                 )}
1902 |               </ArrayField>
1903 |             </Form>
1904 |           </Spin>
1905 |         </Card>
1906 |       </PreviewText.Placeholder>
1907 |     </div>
1908 |   )
1909 | }
1910 | ```
1911 | 
```
Page 48/52FirstPrevNextLast