#
tokens: 49370/50000 4/1152 files (page 38/52)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 38 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

--------------------------------------------------------------------------------
/packages/next/docs/components/ArrayItems.md:
--------------------------------------------------------------------------------

```markdown
  1 | # ArrayItems
  2 | 
  3 | > Self-increment list, suitable for simple self-increment editing scenes, or for scenes with high space requirements
  4 | >
  5 | > Note: This component is only applicable to Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormItem,
 13 |   Input,
 14 |   Editable,
 15 |   Select,
 16 |   DatePicker,
 17 |   ArrayItems,
 18 |   FormButtonGroup,
 19 |   Submit,
 20 |   Space,
 21 | } from '@formily/next'
 22 | import { createForm } from '@formily/core'
 23 | import { FormProvider, createSchemaField } from '@formily/react'
 24 | 
 25 | const SchemaField = createSchemaField({
 26 |   components: {
 27 |     FormItem,
 28 |     DatePicker,
 29 |     Editable,
 30 |     Space,
 31 |     Input,
 32 |     Select,
 33 |     ArrayItems,
 34 |   },
 35 | })
 36 | 
 37 | const form = createForm()
 38 | 
 39 | export default () => {
 40 |   return (
 41 |     <FormProvider form={form}>
 42 |       <SchemaField>
 43 |         <SchemaField.Array
 44 |           name="string_array"
 45 |           title="string array"
 46 |           x-decorator="FormItem"
 47 |           x-component="ArrayItems"
 48 |         >
 49 |           <SchemaField.Void x-component="Space">
 50 |             <SchemaField.Void
 51 |               x-decorator="FormItem"
 52 |               x-component="ArrayItems.SortHandle"
 53 |             />
 54 |             <SchemaField.String
 55 |               x-decorator="FormItem"
 56 |               required
 57 |               name="input"
 58 |               x-component="Input"
 59 |             />
 60 |             <SchemaField.Void
 61 |               x-decorator="FormItem"
 62 |               x-component="ArrayItems.Remove"
 63 |             />
 64 |             <SchemaField.Void
 65 |               x-decorator="FormItem"
 66 |               x-component="ArrayItems.Copy"
 67 |             />
 68 |           </SchemaField.Void>
 69 |           <SchemaField.Void
 70 |             x-component="ArrayItems.Addition"
 71 |             title="Add entry"
 72 |           />
 73 |         </SchemaField.Array>
 74 |         <SchemaField.Array
 75 |           name="array"
 76 |           title="Object array"
 77 |           x-decorator="FormItem"
 78 |           x-component="ArrayItems"
 79 |         >
 80 |           <SchemaField.Object>
 81 |             <SchemaField.Void x-component="Space">
 82 |               <SchemaField.Void
 83 |                 x-decorator="FormItem"
 84 |                 x-component="ArrayItems.SortHandle"
 85 |               />
 86 |               <SchemaField.String
 87 |                 x-decorator="FormItem"
 88 |                 required
 89 |                 title="date"
 90 |                 name="date"
 91 |                 x-component="DatePicker.RangePicker"
 92 |                 x-component-props={{
 93 |                   style: {
 94 |                     width: 160,
 95 |                   },
 96 |                 }}
 97 |               />
 98 |               <SchemaField.String
 99 |                 x-decorator="FormItem"
100 |                 required
101 |                 title="input box"
102 |                 name="input"
103 |                 x-component="Input"
104 |               />
105 |               <SchemaField.String
106 |                 x-decorator="FormItem"
107 |                 required
108 |                 title="select box"
109 |                 name="select"
110 |                 enum={[
111 |                   { label: 'Option 1', value: 1 },
112 |                   { label: 'Option 2', value: 2 },
113 |                 ]}
114 |                 x-component="Select"
115 |                 x-component-props={{
116 |                   style: {
117 |                     width: 160,
118 |                   },
119 |                 }}
120 |               />
121 |               <SchemaField.Void
122 |                 x-decorator="FormItem"
123 |                 x-component="ArrayItems.Remove"
124 |               />
125 |               <SchemaField.Void
126 |                 x-decorator="FormItem"
127 |                 x-component="ArrayItems.Copy"
128 |               />
129 |             </SchemaField.Void>
130 |           </SchemaField.Object>
131 |           <SchemaField.Void
132 |             x-component="ArrayItems.Addition"
133 |             title="Add entry"
134 |           />
135 |         </SchemaField.Array>
136 |         <SchemaField.Array
137 |           name="array2"
138 |           title="Object array"
139 |           x-decorator="FormItem"
140 |           x-component="ArrayItems"
141 |           x-component-props={{ style: { width: 300 } }}
142 |         >
143 |           <SchemaField.Object x-decorator="ArrayItems.Item">
144 |             <SchemaField.Void
145 |               x-decorator="FormItem"
146 |               x-component="ArrayItems.SortHandle"
147 |             />
148 |             <SchemaField.String
149 |               x-decorator="Editable"
150 |               title="input box"
151 |               name="input"
152 |               x-component="Input"
153 |             />
154 |             <SchemaField.Object
155 |               name="config"
156 |               x-component="Editable.Popover"
157 |               required
158 |               title="Configure complex data"
159 |               x-reactions={(field) =>
160 |                 (field.title = field.value?.input || field.title)
161 |               }
162 |             >
163 |               <SchemaField.String
164 |                 x-decorator="FormItem"
165 |                 required
166 |                 title="date"
167 |                 name="date"
168 |                 x-component="DatePicker.RangePicker"
169 |                 x-component-props={{
170 |                   style: { width: '100%' },
171 |                   followTrigger: true,
172 |                 }}
173 |               />
174 |               <SchemaField.String
175 |                 x-decorator="FormItem"
176 |                 required
177 |                 title="input box"
178 |                 name="input"
179 |                 x-component="Input"
180 |               />
181 |             </SchemaField.Object>
182 |             <SchemaField.Void
183 |               x-decorator="FormItem"
184 |               x-component="ArrayItems.Remove"
185 |             />
186 |           </SchemaField.Object>
187 |           <SchemaField.Void
188 |             x-component="ArrayItems.Addition"
189 |             title="Add entry"
190 |           />
191 |         </SchemaField.Array>
192 |       </SchemaField>
193 |       <FormButtonGroup>
194 |         <Submit onSubmit={console.log}>Submit</Submit>
195 |       </FormButtonGroup>
196 |     </FormProvider>
197 |   )
198 | }
199 | ```
200 | 
201 | ## JSON Schema case
202 | 
203 | ```tsx
204 | import React from 'react'
205 | import {
206 |   FormItem,
207 |   Editable,
208 |   Input,
209 |   Select,
210 |   Radio,
211 |   DatePicker,
212 |   ArrayItems,
213 |   FormButtonGroup,
214 |   Submit,
215 |   Space,
216 | } from '@formily/next'
217 | import { createForm } from '@formily/core'
218 | import { FormProvider, createSchemaField } from '@formily/react'
219 | 
220 | const SchemaField = createSchemaField({
221 |   components: {
222 |     FormItem,
223 |     Editable,
224 |     DatePicker,
225 |     Space,
226 |     Radio,
227 |     Input,
228 |     Select,
229 |     ArrayItems,
230 |   },
231 | })
232 | 
233 | const form = createForm()
234 | 
235 | const schema = {
236 |   type: 'object',
237 |   properties: {
238 |     string_array: {
239 |       type: 'array',
240 |       'x-component': 'ArrayItems',
241 |       'x-decorator': 'FormItem',
242 |       title: 'String array',
243 |       items: {
244 |         type: 'void',
245 |         'x-component': 'Space',
246 |         properties: {
247 |           sort: {
248 |             type: 'void',
249 |             'x-decorator': 'FormItem',
250 |             'x-component': 'ArrayItems.SortHandle',
251 |           },
252 |           input: {
253 |             type: 'string',
254 |             'x-decorator': 'FormItem',
255 |             'x-component': 'Input',
256 |           },
257 |           remove: {
258 |             type: 'void',
259 |             'x-decorator': 'FormItem',
260 |             'x-component': 'ArrayItems.Remove',
261 |           },
262 |         },
263 |       },
264 |       properties: {
265 |         add: {
266 |           type: 'void',
267 |           title: 'Add entry',
268 |           'x-component': 'ArrayItems.Addition',
269 |         },
270 |       },
271 |     },
272 |     array: {
273 |       type: 'array',
274 |       'x-component': 'ArrayItems',
275 |       'x-decorator': 'FormItem',
276 |       title: 'Object array',
277 |       items: {
278 |         type: 'object',
279 |         properties: {
280 |           space: {
281 |             type: 'void',
282 |             'x-component': 'Space',
283 |             properties: {
284 |               sort: {
285 |                 type: 'void',
286 |                 'x-decorator': 'FormItem',
287 |                 'x-component': 'ArrayItems.SortHandle',
288 |               },
289 |               date: {
290 |                 type: 'string',
291 |                 title: 'Date',
292 |                 'x-decorator': 'FormItem',
293 |                 'x-component': 'DatePicker.RangePicker',
294 |                 'x-component-props': {
295 |                   style: {
296 |                     width: 160,
297 |                   },
298 |                 },
299 |               },
300 |               input: {
301 |                 type: 'string',
302 |                 title: 'input box',
303 |                 'x-decorator': 'FormItem',
304 |                 'x-component': 'Input',
305 |               },
306 |               select: {
307 |                 type: 'string',
308 |                 title: 'drop-down box',
309 |                 enum: [
310 |                   { label: 'Option 1', value: 1 },
311 |                   { label: 'Option 2', value: 2 },
312 |                 ],
313 |                 'x-decorator': 'FormItem',
314 |                 'x-component': 'Select',
315 |                 'x-component-props': {
316 |                   style: {
317 |                     width: 160,
318 |                   },
319 |                 },
320 |               },
321 |               remove: {
322 |                 type: 'void',
323 |                 'x-decorator': 'FormItem',
324 |                 'x-component': 'ArrayItems.Remove',
325 |               },
326 |             },
327 |           },
328 |         },
329 |       },
330 |       properties: {
331 |         add: {
332 |           type: 'void',
333 |           title: 'Add entry',
334 |           'x-component': 'ArrayItems.Addition',
335 |         },
336 |       },
337 |     },
338 |     array2: {
339 |       type: 'array',
340 |       'x-component': 'ArrayItems',
341 |       'x-decorator': 'FormItem',
342 |       'x-component-props': { style: { width: 300 } },
343 |       title: 'Object array',
344 |       items: {
345 |         type: 'object',
346 |         'x-decorator': 'ArrayItems.Item',
347 |         properties: {
348 |           sort: {
349 |             type: 'void',
350 |             'x-decorator': 'FormItem',
351 |             'x-component': 'ArrayItems.SortHandle',
352 |           },
353 | 
354 |           input: {
355 |             type: 'string',
356 |             title: 'input box',
357 |             'x-decorator': 'Editable',
358 |             'x-component': 'Input',
359 |           },
360 |           config: {
361 |             type: 'object',
362 |             title: 'Configure complex data',
363 |             'x-component': 'Editable.Popover',
364 |             'x-reactions':
365 |               '{{(field)=>field.title = field.value && field.value.input || field.title}}',
366 |             properties: {
367 |               date: {
368 |                 type: 'string',
369 |                 title: 'Date',
370 |                 'x-decorator': 'FormItem',
371 |                 'x-component': 'DatePicker.RangePicker',
372 |                 'x-component-props': {
373 |                   style: {
374 |                     width: 160,
375 |                   },
376 |                   followTrigger: true,
377 |                 },
378 |               },
379 |               input: {
380 |                 type: 'string',
381 |                 title: 'input box',
382 |                 'x-decorator': 'FormItem',
383 |                 'x-component': 'Input',
384 |               },
385 |               select: {
386 |                 type: 'string',
387 |                 title: 'drop-down box',
388 |                 enum: [
389 |                   { label: 'Option 1', value: 1 },
390 |                   { label: 'Option 2', value: 2 },
391 |                 ],
392 |                 'x-decorator': 'FormItem',
393 |                 'x-component': 'Select',
394 |                 'x-component-props': {
395 |                   style: {
396 |                     width: 160,
397 |                   },
398 |                 },
399 |               },
400 |             },
401 |           },
402 |           remove: {
403 |             type: 'void',
404 |             'x-decorator': 'FormItem',
405 |             'x-component': 'ArrayItems.Remove',
406 |           },
407 |         },
408 |       },
409 |       properties: {
410 |         add: {
411 |           type: 'void',
412 |           title: 'Add entry',
413 |           'x-component': 'ArrayItems.Addition',
414 |         },
415 |       },
416 |     },
417 |   },
418 | }
419 | 
420 | export default () => {
421 |   return (
422 |     <FormProvider form={form}>
423 |       <SchemaField schema={schema} />
424 |       <FormButtonGroup>
425 |         <Submit onSubmit={console.log}>Submit</Submit>
426 |       </FormButtonGroup>
427 |     </FormProvider>
428 |   )
429 | }
430 | ```
431 | 
432 | ## Effects linkage case
433 | 
434 | ```tsx
435 | import React from 'react'
436 | import {
437 |   FormItem,
438 |   Input,
439 |   ArrayItems,
440 |   Editable,
441 |   FormButtonGroup,
442 |   Submit,
443 |   Space,
444 | } from '@formily/next'
445 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
446 | import { FormProvider, createSchemaField } from '@formily/react'
447 | 
448 | const SchemaField = createSchemaField({
449 |   components: {
450 |     Space,
451 |     Editable,
452 |     FormItem,
453 |     Input,
454 |     ArrayItems,
455 |   },
456 | })
457 | 
458 | const form = createForm({
459 |   effects: () => {
460 |     //Active linkage mode
461 |     onFieldChange('array.*.aa', ['value'], (field, form) => {
462 |       form.setFieldState(field.query('.bb'), (state) => {
463 |         state.visible = field.value != '123'
464 |       })
465 |     })
466 |     //Passive linkage mode
467 |     onFieldReact('array.*.dd', (field) => {
468 |       field.visible = field.query('.cc').get('value') != '123'
469 |     })
470 |   },
471 | })
472 | 
473 | export default () => {
474 |   return (
475 |     <FormProvider form={form}>
476 |       <SchemaField>
477 |         <SchemaField.Array
478 |           name="array"
479 |           title="Object array"
480 |           maxItems={3}
481 |           x-decorator="FormItem"
482 |           x-component="ArrayItems"
483 |           x-component-props={{
484 |             style: {
485 |               width: 300,
486 |             },
487 |           }}
488 |         >
489 |           <SchemaField.Object x-decorator="ArrayItems.Item">
490 |             <SchemaField.Void x-component="Space">
491 |               <SchemaField.Void
492 |                 x-decorator="FormItem"
493 |                 x-component="ArrayItems.SortHandle"
494 |               />
495 |               <SchemaField.Void
496 |                 x-decorator="FormItem"
497 |                 x-component="ArrayItems.Index"
498 |               />
499 |             </SchemaField.Void>
500 |             <SchemaField.Void
501 |               x-component="Editable.Popover"
502 |               title="Configuration data"
503 |             >
504 |               <SchemaField.String
505 |                 name="aa"
506 |                 x-decorator="FormItem"
507 |                 title="AA"
508 |                 required
509 |                 description="AA hide BB when entering 123"
510 |                 x-component="Input"
511 |               />
512 |               <SchemaField.String
513 |                 name="bb"
514 |                 x-decorator="FormItem"
515 |                 title="BB"
516 |                 required
517 |                 x-component="Input"
518 |               />
519 |               <SchemaField.String
520 |                 name="cc"
521 |                 x-decorator="FormItem"
522 |                 title="CC"
523 |                 required
524 |                 description="Hide DD when CC enters 123"
525 |                 x-component="Input"
526 |               />
527 |               <SchemaField.String
528 |                 name="dd"
529 |                 x-decorator="FormItem"
530 |                 title="DD"
531 |                 required
532 |                 x-component="Input"
533 |               />
534 |             </SchemaField.Void>
535 |             <SchemaField.Void x-component="Space">
536 |               <SchemaField.Void
537 |                 x-decorator="FormItem"
538 |                 x-component="ArrayItems.Remove"
539 |               />
540 |               <SchemaField.Void
541 |                 x-decorator="FormItem"
542 |                 x-component="ArrayItems.MoveUp"
543 |               />
544 |               <SchemaField.Void
545 |                 x-decorator="FormItem"
546 |                 x-component="ArrayItems.MoveDown"
547 |               />
548 |             </SchemaField.Void>
549 |           </SchemaField.Object>
550 |           <SchemaField.Void
551 |             x-component="ArrayItems.Addition"
552 |             title="Add entry"
553 |           />
554 |         </SchemaField.Array>
555 |       </SchemaField>
556 |       <FormButtonGroup>
557 |         <Submit onSubmit={console.log}>Submit</Submit>
558 |       </FormButtonGroup>
559 |     </FormProvider>
560 |   )
561 | }
562 | ```
563 | 
564 | ## JSON Schema linkage case
565 | 
566 | ```tsx
567 | import React from 'react'
568 | import {
569 |   FormItem,
570 |   Input,
571 |   ArrayItems,
572 |   Editable,
573 |   FormButtonGroup,
574 |   Submit,
575 |   Space,
576 | } from '@formily/next'
577 | import { createForm } from '@formily/core'
578 | import { FormProvider, createSchemaField } from '@formily/react'
579 | 
580 | const SchemaField = createSchemaField({
581 |   components: {
582 |     Space,
583 |     Editable,
584 |     FormItem,
585 |     Input,
586 |     ArrayItems,
587 |   },
588 | })
589 | 
590 | const form = createForm()
591 | 
592 | const schema = {
593 |   type: 'object',
594 |   properties: {
595 |     array: {
596 |       type: 'array',
597 |       'x-component': 'ArrayItems',
598 |       'x-decorator': 'FormItem',
599 |       maxItems: 3,
600 |       title: 'Object array',
601 |       'x-component-props': { style: { width: 300 } },
602 |       items: {
603 |         type: 'object',
604 |         'x-decorator': 'ArrayItems.Item',
605 |         properties: {
606 |           left: {
607 |             type: 'void',
608 |             'x-component': 'Space',
609 |             properties: {
610 |               sort: {
611 |                 type: 'void',
612 |                 'x-decorator': 'FormItem',
613 |                 'x-component': 'ArrayItems.SortHandle',
614 |               },
615 |               index: {
616 |                 type: 'void',
617 |                 'x-decorator': 'FormItem',
618 |                 'x-component': 'ArrayItems.Index',
619 |               },
620 |             },
621 |           },
622 |           edit: {
623 |             type: 'void',
624 |             'x-component': 'Editable.Popover',
625 |             title: 'Configuration data',
626 |             properties: {
627 |               aa: {
628 |                 type: 'string',
629 |                 'x-decorator': 'FormItem',
630 |                 title: 'AA',
631 |                 required: true,
632 |                 'x-component': 'Input',
633 |                 description: 'Enter 123',
634 |               },
635 |               bb: {
636 |                 type: 'string',
637 |                 title: 'BB',
638 |                 required: true,
639 |                 'x-decorator': 'FormItem',
640 |                 'x-component': 'Input',
641 |                 'x-reactions': [
642 |                   {
643 |                     dependencies: ['.aa'],
644 |                     when: "{{$deps[0] != '123'}}",
645 |                     fulfill: {
646 |                       schema: {
647 |                         title: 'BB',
648 |                         'x-disabled': true,
649 |                       },
650 |                     },
651 |                     otherwise: {
652 |                       schema: {
653 |                         title: 'Changed',
654 |                         'x-disabled': false,
655 |                       },
656 |                     },
657 |                   },
658 |                 ],
659 |               },
660 |             },
661 |           },
662 |           right: {
663 |             type: 'void',
664 |             'x-component': 'Space',
665 |             properties: {
666 |               remove: {
667 |                 type: 'void',
668 |                 'x-component': 'ArrayItems.Remove',
669 |               },
670 |               moveUp: {
671 |                 type: 'void',
672 |                 'x-component': 'ArrayItems.MoveUp',
673 |               },
674 |               moveDown: {
675 |                 type: 'void',
676 |                 'x-component': 'ArrayItems.MoveDown',
677 |               },
678 |             },
679 |           },
680 |         },
681 |       },
682 |       properties: {
683 |         addition: {
684 |           type: 'void',
685 |           title: 'Add entry',
686 |           'x-component': 'ArrayItems.Addition',
687 |         },
688 |       },
689 |     },
690 |   },
691 | }
692 | 
693 | export default () => {
694 |   return (
695 |     <FormProvider form={form}>
696 |       <SchemaField schema={schema} />
697 |       <FormButtonGroup>
698 |         <Submit onSubmit={console.log}>Submit</Submit>
699 |       </FormButtonGroup>
700 |     </FormProvider>
701 |   )
702 | }
703 | ```
704 | 
705 | ## API
706 | 
707 | ### ArrayItems
708 | 
709 | Extended attributes
710 | 
711 | | Property name | Type                      | Description     | Default value |
712 | | ------------- | ------------------------- | --------------- | ------------- |
713 | | onAdd         | `(index: number) => void` | add method      |               |
714 | | onRemove      | `(index: number) => void` | remove method   |               |
715 | | onCopy        | `(index: number) => void` | copy method     |               |
716 | | onMoveUp      | `(index: number) => void` | moveUp method   |               |
717 | | onMoveDown    | `(index: number) => void` | moveDown method |               |
718 | 
719 | Other Inherit HTMLDivElement Props
720 | 
721 | ### ArrayItems.Item
722 | 
723 | > List block
724 | 
725 | Inherit HTMLDivElement Props
726 | 
727 | Extended attributes
728 | 
729 | | Property name | Type                | Description           | Default value |
730 | | ------------- | ------------------- | --------------------- | ------------- |
731 | | type          | `'card' \|'divide'` | card or dividing line |               |
732 | 
733 | ### ArrayItems.SortHandle
734 | 
735 | > Drag handle
736 | 
737 | Reference https://ant.design/components/icon-cn/
738 | 
739 | ### ArrayItems.Addition
740 | 
741 | > Add button
742 | 
743 | Extended attributes
744 | 
745 | | Property name | Type                 | Description   | Default value |
746 | | ------------- | -------------------- | ------------- | ------------- |
747 | | title         | ReactText            | Copywriting   |               |
748 | | method        | `'push' \|'unshift'` | add method    | `'push'`      |
749 | | defaultValue  | `any`                | Default value |               |
750 | 
751 | Other references https://fusion.design/pc/component/basic/button
752 | 
753 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
754 | 
755 | ### ArrayItems.Copy
756 | 
757 | > Copy button
758 | 
759 | Extended attributes
760 | 
761 | | Property name | Type                 | Description | Default value |
762 | | ------------- | -------------------- | ----------- | ------------- |
763 | | title         | ReactText            | Copywriting |               |
764 | | method        | `'push' \|'unshift'` | add method  | `'push'`      |
765 | 
766 | Other references https://fusion.design/pc/component/basic/button
767 | 
768 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
769 | 
770 | ### ArrayItems.Remove
771 | 
772 | > Delete button
773 | 
774 | | Property name | Type      | Description | Default value |
775 | | ------------- | --------- | ----------- | ------------- |
776 | | title         | ReactText | Copywriting |               |
777 | 
778 | Other references https://ant.design/components/icon-cn/
779 | 
780 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
781 | 
782 | ### ArrayItems.MoveDown
783 | 
784 | > Move down button
785 | 
786 | | Property name | Type      | Description | Default value |
787 | | ------------- | --------- | ----------- | ------------- |
788 | | title         | ReactText | Copywriting |               |
789 | 
790 | Other references https://ant.design/components/icon-cn/
791 | 
792 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
793 | 
794 | ### ArrayItems.MoveUp
795 | 
796 | > Move up button
797 | 
798 | | Property name | Type      | Description | Default value |
799 | | ------------- | --------- | ----------- | ------------- |
800 | | title         | ReactText | Copywriting |               |
801 | 
802 | Other references https://ant.design/components/icon-cn/
803 | 
804 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
805 | 
806 | ### ArrayItems.Index
807 | 
808 | > Index Renderer
809 | 
810 | No attributes
811 | 
812 | ### ArrayItems.useIndex
813 | 
814 | > Read the React Hook of the current rendering row index
815 | 
816 | ### ArrayItems.useRecord
817 | 
818 | > Read the React Hook of the current rendering row
819 | 
```

--------------------------------------------------------------------------------
/packages/antd/docs/components/ArrayItems.md:
--------------------------------------------------------------------------------

```markdown
  1 | # ArrayItems
  2 | 
  3 | > Self-increment list, suitable for simple self-increment editing scenes, or for scenes with high space requirements
  4 | >
  5 | > Note: This component is only applicable to Schema scenarios
  6 | 
  7 | ## Markup Schema example
  8 | 
  9 | ```tsx
 10 | import React from 'react'
 11 | import {
 12 |   FormItem,
 13 |   Input,
 14 |   Editable,
 15 |   Select,
 16 |   DatePicker,
 17 |   ArrayItems,
 18 |   FormButtonGroup,
 19 |   Submit,
 20 |   Space,
 21 | } from '@formily/antd'
 22 | import { createForm } from '@formily/core'
 23 | import { FormProvider, createSchemaField } from '@formily/react'
 24 | 
 25 | const SchemaField = createSchemaField({
 26 |   components: {
 27 |     FormItem,
 28 |     DatePicker,
 29 |     Editable,
 30 |     Space,
 31 |     Input,
 32 |     Select,
 33 |     ArrayItems,
 34 |   },
 35 | })
 36 | 
 37 | const form = createForm()
 38 | 
 39 | export default () => {
 40 |   return (
 41 |     <FormProvider form={form}>
 42 |       <SchemaField>
 43 |         <SchemaField.Array
 44 |           name="string_array"
 45 |           title="string array"
 46 |           x-decorator="FormItem"
 47 |           x-component="ArrayItems"
 48 |         >
 49 |           <SchemaField.Void x-component="Space">
 50 |             <SchemaField.Void
 51 |               x-decorator="FormItem"
 52 |               x-component="ArrayItems.SortHandle"
 53 |             />
 54 |             <SchemaField.String
 55 |               x-decorator="FormItem"
 56 |               required
 57 |               name="input"
 58 |               x-component="Input"
 59 |             />
 60 |             <SchemaField.Void
 61 |               x-decorator="FormItem"
 62 |               x-component="ArrayItems.Remove"
 63 |             />
 64 |             <SchemaField.Void
 65 |               x-decorator="FormItem"
 66 |               x-component="ArrayItems.Copy"
 67 |             />
 68 |           </SchemaField.Void>
 69 |           <SchemaField.Void
 70 |             x-component="ArrayItems.Addition"
 71 |             title="Add entry"
 72 |           />
 73 |         </SchemaField.Array>
 74 |         <SchemaField.Array
 75 |           name="array"
 76 |           title="Object array"
 77 |           x-decorator="FormItem"
 78 |           x-component="ArrayItems"
 79 |         >
 80 |           <SchemaField.Object>
 81 |             <SchemaField.Void x-component="Space">
 82 |               <SchemaField.Void
 83 |                 x-decorator="FormItem"
 84 |                 x-component="ArrayItems.SortHandle"
 85 |               />
 86 |               <SchemaField.String
 87 |                 x-decorator="FormItem"
 88 |                 required
 89 |                 title="date"
 90 |                 name="date"
 91 |                 x-component="DatePicker.RangePicker"
 92 |                 x-component-props={{
 93 |                   style: {
 94 |                     width: 160,
 95 |                   },
 96 |                 }}
 97 |               />
 98 |               <SchemaField.String
 99 |                 x-decorator="FormItem"
100 |                 required
101 |                 title="input box"
102 |                 name="input"
103 |                 x-component="Input"
104 |               />
105 |               <SchemaField.String
106 |                 x-decorator="FormItem"
107 |                 required
108 |                 title="select box"
109 |                 name="select"
110 |                 enum={[
111 |                   { label: 'Option 1', value: 1 },
112 |                   { label: 'Option 2', value: 2 },
113 |                 ]}
114 |                 x-component="Select"
115 |                 x-component-props={{
116 |                   style: {
117 |                     width: 160,
118 |                   },
119 |                 }}
120 |               />
121 |               <SchemaField.Void
122 |                 x-decorator="FormItem"
123 |                 x-component="ArrayItems.Remove"
124 |               />
125 |             </SchemaField.Void>
126 |           </SchemaField.Object>
127 |           <SchemaField.Void
128 |             x-component="ArrayItems.Addition"
129 |             title="Add entry"
130 |           />
131 |         </SchemaField.Array>
132 |         <SchemaField.Array
133 |           name="array2"
134 |           title="Object array"
135 |           x-decorator="FormItem"
136 |           x-component="ArrayItems"
137 |           x-component-props={{ style: { width: 300 } }}
138 |         >
139 |           <SchemaField.Object x-decorator="ArrayItems.Item">
140 |             <SchemaField.Void
141 |               x-decorator="FormItem"
142 |               x-component="ArrayItems.SortHandle"
143 |             />
144 |             <SchemaField.String
145 |               x-decorator="Editable"
146 |               title="input box"
147 |               name="input"
148 |               x-component="Input"
149 |               x-component-props={{ bordered: false }}
150 |             />
151 |             <SchemaField.Object
152 |               name="config"
153 |               x-component="Editable.Popover"
154 |               required
155 |               title="Configure complex data"
156 |               x-reactions={(field) => {
157 |                 field.title = field.value?.input || field.title
158 |               }}
159 |             >
160 |               <SchemaField.String
161 |                 x-decorator="FormItem"
162 |                 required
163 |                 title="date"
164 |                 name="date"
165 |                 x-component="DatePicker.RangePicker"
166 |                 x-component-props={{ style: { width: '100%' } }}
167 |               />
168 |               <SchemaField.String
169 |                 x-decorator="FormItem"
170 |                 required
171 |                 title="input box"
172 |                 name="input"
173 |                 x-component="Input"
174 |               />
175 |             </SchemaField.Object>
176 |             <SchemaField.Void
177 |               x-decorator="FormItem"
178 |               x-component="ArrayItems.Remove"
179 |             />
180 |           </SchemaField.Object>
181 |           <SchemaField.Void
182 |             x-component="ArrayItems.Addition"
183 |             title="Add entry"
184 |           />
185 |         </SchemaField.Array>
186 |       </SchemaField>
187 |       <FormButtonGroup>
188 |         <Submit onSubmit={console.log}>Submit</Submit>
189 |       </FormButtonGroup>
190 |     </FormProvider>
191 |   )
192 | }
193 | ```
194 | 
195 | ## JSON Schema case
196 | 
197 | ```tsx
198 | import React from 'react'
199 | import {
200 |   FormItem,
201 |   Editable,
202 |   Input,
203 |   Select,
204 |   Radio,
205 |   DatePicker,
206 |   ArrayItems,
207 |   FormButtonGroup,
208 |   Submit,
209 |   Space,
210 | } from '@formily/antd'
211 | import { createForm } from '@formily/core'
212 | import { FormProvider, createSchemaField } from '@formily/react'
213 | 
214 | const SchemaField = createSchemaField({
215 |   components: {
216 |     FormItem,
217 |     Editable,
218 |     DatePicker,
219 |     Space,
220 |     Radio,
221 |     Input,
222 |     Select,
223 |     ArrayItems,
224 |   },
225 | })
226 | 
227 | const form = createForm()
228 | 
229 | const schema = {
230 |   type: 'object',
231 |   properties: {
232 |     string_array: {
233 |       type: 'array',
234 |       'x-component': 'ArrayItems',
235 |       'x-decorator': 'FormItem',
236 |       title: 'String array',
237 |       items: {
238 |         type: 'void',
239 |         'x-component': 'Space',
240 |         properties: {
241 |           sort: {
242 |             type: 'void',
243 |             'x-decorator': 'FormItem',
244 |             'x-component': 'ArrayItems.SortHandle',
245 |           },
246 |           input: {
247 |             type: 'string',
248 |             'x-decorator': 'FormItem',
249 |             'x-component': 'Input',
250 |           },
251 |           remove: {
252 |             type: 'void',
253 |             'x-decorator': 'FormItem',
254 |             'x-component': 'ArrayItems.Remove',
255 |           },
256 |         },
257 |       },
258 |       properties: {
259 |         add: {
260 |           type: 'void',
261 |           title: 'Add entry',
262 |           'x-component': 'ArrayItems.Addition',
263 |         },
264 |       },
265 |     },
266 |     array: {
267 |       type: 'array',
268 |       'x-component': 'ArrayItems',
269 |       'x-decorator': 'FormItem',
270 |       title: 'Object array',
271 |       items: {
272 |         type: 'object',
273 |         properties: {
274 |           space: {
275 |             type: 'void',
276 |             'x-component': 'Space',
277 |             properties: {
278 |               sort: {
279 |                 type: 'void',
280 |                 'x-decorator': 'FormItem',
281 |                 'x-component': 'ArrayItems.SortHandle',
282 |               },
283 |               date: {
284 |                 type: 'string',
285 |                 title: 'Date',
286 |                 'x-decorator': 'FormItem',
287 |                 'x-component': 'DatePicker.RangePicker',
288 |                 'x-component-props': {
289 |                   style: {
290 |                     width: 160,
291 |                   },
292 |                 },
293 |               },
294 |               input: {
295 |                 type: 'string',
296 |                 title: 'input box',
297 |                 'x-decorator': 'FormItem',
298 |                 'x-component': 'Input',
299 |               },
300 |               select: {
301 |                 type: 'string',
302 |                 title: 'drop-down box',
303 |                 enum: [
304 |                   { label: 'Option 1', value: 1 },
305 |                   { label: 'Option 2', value: 2 },
306 |                 ],
307 |                 'x-decorator': 'FormItem',
308 |                 'x-component': 'Select',
309 |                 'x-component-props': {
310 |                   style: {
311 |                     width: 160,
312 |                   },
313 |                 },
314 |               },
315 |               remove: {
316 |                 type: 'void',
317 |                 'x-decorator': 'FormItem',
318 |                 'x-component': 'ArrayItems.Remove',
319 |               },
320 |             },
321 |           },
322 |         },
323 |       },
324 |       properties: {
325 |         add: {
326 |           type: 'void',
327 |           title: 'Add entry',
328 |           'x-component': 'ArrayItems.Addition',
329 |         },
330 |       },
331 |     },
332 |     array2: {
333 |       type: 'array',
334 |       'x-component': 'ArrayItems',
335 |       'x-decorator': 'FormItem',
336 |       'x-component-props': { style: { width: 300 } },
337 |       title: 'Object array',
338 |       items: {
339 |         type: 'object',
340 |         'x-decorator': 'ArrayItems.Item',
341 |         properties: {
342 |           sort: {
343 |             type: 'void',
344 |             'x-decorator': 'FormItem',
345 |             'x-component': 'ArrayItems.SortHandle',
346 |           },
347 | 
348 |           input: {
349 |             type: 'string',
350 |             title: 'input box',
351 |             'x-decorator': 'Editable',
352 |             'x-component': 'Input',
353 |             'x-component-props': {
354 |               bordered: false,
355 |             },
356 |           },
357 |           config: {
358 |             type: 'object',
359 |             title: 'Configure complex data',
360 |             'x-component': 'Editable.Popover',
361 |             'x-reactions':
362 |               '{{(field)=>field.title = field.value && field.value.input || field.title}}',
363 |             properties: {
364 |               date: {
365 |                 type: 'string',
366 |                 title: 'Date',
367 |                 'x-decorator': 'FormItem',
368 |                 'x-component': 'DatePicker.RangePicker',
369 |                 'x-component-props': {
370 |                   style: {
371 |                     width: 160,
372 |                   },
373 |                 },
374 |               },
375 |               input: {
376 |                 type: 'string',
377 |                 title: 'input box',
378 |                 'x-decorator': 'FormItem',
379 |                 'x-component': 'Input',
380 |               },
381 |               select: {
382 |                 type: 'string',
383 |                 title: 'drop-down box',
384 |                 enum: [
385 |                   { label: 'Option 1', value: 1 },
386 |                   { label: 'Option 2', value: 2 },
387 |                 ],
388 |                 'x-decorator': 'FormItem',
389 |                 'x-component': 'Select',
390 |                 'x-component-props': {
391 |                   style: {
392 |                     width: 160,
393 |                   },
394 |                 },
395 |               },
396 |             },
397 |           },
398 |           remove: {
399 |             type: 'void',
400 |             'x-decorator': 'FormItem',
401 |             'x-component': 'ArrayItems.Remove',
402 |           },
403 |         },
404 |       },
405 |       properties: {
406 |         add: {
407 |           type: 'void',
408 |           title: 'Add entry',
409 |           'x-component': 'ArrayItems.Addition',
410 |         },
411 |       },
412 |     },
413 |   },
414 | }
415 | 
416 | export default () => {
417 |   return (
418 |     <FormProvider form={form}>
419 |       <SchemaField schema={schema} />
420 |       <FormButtonGroup>
421 |         <Submit onSubmit={console.log}>Submit</Submit>
422 |       </FormButtonGroup>
423 |     </FormProvider>
424 |   )
425 | }
426 | ```
427 | 
428 | ## Effects linkage case
429 | 
430 | ```tsx
431 | import React from 'react'
432 | import {
433 |   FormItem,
434 |   Input,
435 |   ArrayItems,
436 |   Editable,
437 |   FormButtonGroup,
438 |   Submit,
439 |   Space,
440 | } from '@formily/antd'
441 | import { createForm, onFieldChange, onFieldReact } from '@formily/core'
442 | import { FormProvider, createSchemaField } from '@formily/react'
443 | 
444 | const SchemaField = createSchemaField({
445 |   components: {
446 |     Space,
447 |     Editable,
448 |     FormItem,
449 |     Input,
450 |     ArrayItems,
451 |   },
452 | })
453 | 
454 | const form = createForm({
455 |   effects: () => {
456 |     //Active linkage mode
457 |     onFieldChange('array.*.aa', ['value'], (field, form) => {
458 |       form.setFieldState(field.query('.bb'), (state) => {
459 |         state.visible = field.value != '123'
460 |       })
461 |     })
462 |     //Passive linkage mode
463 |     onFieldReact('array.*.dd', (field) => {
464 |       field.visible = field.query('.cc').get('value') != '123'
465 |     })
466 |   },
467 | })
468 | 
469 | export default () => {
470 |   return (
471 |     <FormProvider form={form}>
472 |       <SchemaField>
473 |         <SchemaField.Array
474 |           name="array"
475 |           title="Object array"
476 |           maxItems={3}
477 |           x-decorator="FormItem"
478 |           x-component="ArrayItems"
479 |           x-component-props={{
480 |             style: {
481 |               width: 300,
482 |             },
483 |           }}
484 |         >
485 |           <SchemaField.Object x-decorator="ArrayItems.Item">
486 |             <SchemaField.Void x-component="Space">
487 |               <SchemaField.Void
488 |                 x-decorator="FormItem"
489 |                 x-component="ArrayItems.SortHandle"
490 |               />
491 |               <SchemaField.Void
492 |                 x-decorator="FormItem"
493 |                 x-component="ArrayItems.Index"
494 |               />
495 |             </SchemaField.Void>
496 |             <SchemaField.Void
497 |               x-component="Editable.Popover"
498 |               title="Configuration data"
499 |             >
500 |               <SchemaField.String
501 |                 name="aa"
502 |                 x-decorator="FormItem"
503 |                 title="AA"
504 |                 required
505 |                 description="AA hide BB when entering 123"
506 |                 x-component="Input"
507 |               />
508 |               <SchemaField.String
509 |                 name="bb"
510 |                 x-decorator="FormItem"
511 |                 title="BB"
512 |                 required
513 |                 x-component="Input"
514 |               />
515 |               <SchemaField.String
516 |                 name="cc"
517 |                 x-decorator="FormItem"
518 |                 title="CC"
519 |                 required
520 |                 description="Hide DD when CC enters 123"
521 |                 x-component="Input"
522 |               />
523 |               <SchemaField.String
524 |                 name="dd"
525 |                 x-decorator="FormItem"
526 |                 title="DD"
527 |                 required
528 |                 x-component="Input"
529 |               />
530 |             </SchemaField.Void>
531 |             <SchemaField.Void x-component="Space">
532 |               <SchemaField.Void
533 |                 x-decorator="FormItem"
534 |                 x-component="ArrayItems.Remove"
535 |               />
536 |               <SchemaField.Void
537 |                 x-decorator="FormItem"
538 |                 x-component="ArrayItems.MoveUp"
539 |               />
540 |               <SchemaField.Void
541 |                 x-decorator="FormItem"
542 |                 x-component="ArrayItems.MoveDown"
543 |               />
544 |             </SchemaField.Void>
545 |           </SchemaField.Object>
546 |           <SchemaField.Void
547 |             x-component="ArrayItems.Addition"
548 |             title="Add entry"
549 |           />
550 |         </SchemaField.Array>
551 |       </SchemaField>
552 |       <FormButtonGroup>
553 |         <Submit onSubmit={console.log}>Submit</Submit>
554 |       </FormButtonGroup>
555 |     </FormProvider>
556 |   )
557 | }
558 | ```
559 | 
560 | ## JSON Schema linkage case
561 | 
562 | ```tsx
563 | import React from 'react'
564 | import {
565 |   FormItem,
566 |   Input,
567 |   ArrayItems,
568 |   Editable,
569 |   FormButtonGroup,
570 |   Submit,
571 |   Space,
572 | } from '@formily/antd'
573 | import { createForm } from '@formily/core'
574 | import { FormProvider, createSchemaField } from '@formily/react'
575 | 
576 | const SchemaField = createSchemaField({
577 |   components: {
578 |     Space,
579 |     Editable,
580 |     FormItem,
581 |     Input,
582 |     ArrayItems,
583 |   },
584 | })
585 | 
586 | const form = createForm()
587 | 
588 | const schema = {
589 |   type: 'object',
590 |   properties: {
591 |     array: {
592 |       type: 'array',
593 |       'x-component': 'ArrayItems',
594 |       'x-decorator': 'FormItem',
595 |       maxItems: 3,
596 |       title: 'Object array',
597 |       'x-component-props': { style: { width: 300 } },
598 |       items: {
599 |         type: 'object',
600 |         'x-decorator': 'ArrayItems.Item',
601 |         properties: {
602 |           left: {
603 |             type: 'void',
604 |             'x-component': 'Space',
605 |             properties: {
606 |               sort: {
607 |                 type: 'void',
608 |                 'x-decorator': 'FormItem',
609 |                 'x-component': 'ArrayItems.SortHandle',
610 |               },
611 |               index: {
612 |                 type: 'void',
613 |                 'x-decorator': 'FormItem',
614 |                 'x-component': 'ArrayItems.Index',
615 |               },
616 |             },
617 |           },
618 |           edit: {
619 |             type: 'void',
620 |             'x-component': 'Editable.Popover',
621 |             title: 'Configuration data',
622 |             properties: {
623 |               aa: {
624 |                 type: 'string',
625 |                 'x-decorator': 'FormItem',
626 |                 title: 'AA',
627 |                 required: true,
628 |                 'x-component': 'Input',
629 |                 description: 'Enter 123',
630 |               },
631 |               bb: {
632 |                 type: 'string',
633 |                 title: 'BB',
634 |                 required: true,
635 |                 'x-decorator': 'FormItem',
636 |                 'x-component': 'Input',
637 |                 'x-reactions': [
638 |                   {
639 |                     dependencies: ['.aa'],
640 |                     when: "{{$deps[0] != '123'}}",
641 |                     fulfill: {
642 |                       schema: {
643 |                         title: 'BB',
644 |                         'x-disabled': true,
645 |                       },
646 |                     },
647 |                     otherwise: {
648 |                       schema: {
649 |                         title: 'Changed',
650 |                         'x-disabled': false,
651 |                       },
652 |                     },
653 |                   },
654 |                 ],
655 |               },
656 |             },
657 |           },
658 |           right: {
659 |             type: 'void',
660 |             'x-component': 'Space',
661 |             properties: {
662 |               remove: {
663 |                 type: 'void',
664 |                 'x-component': 'ArrayItems.Remove',
665 |               },
666 |               moveUp: {
667 |                 type: 'void',
668 |                 'x-component': 'ArrayItems.MoveUp',
669 |               },
670 |               moveDown: {
671 |                 type: 'void',
672 |                 'x-component': 'ArrayItems.MoveDown',
673 |               },
674 |             },
675 |           },
676 |         },
677 |       },
678 |       properties: {
679 |         addition: {
680 |           type: 'void',
681 |           title: 'Add entry',
682 |           'x-component': 'ArrayItems.Addition',
683 |         },
684 |       },
685 |     },
686 |   },
687 | }
688 | 
689 | export default () => {
690 |   return (
691 |     <FormProvider form={form}>
692 |       <SchemaField schema={schema} />
693 |       <FormButtonGroup>
694 |         <Submit onSubmit={console.log}>Submit</Submit>
695 |       </FormButtonGroup>
696 |     </FormProvider>
697 |   )
698 | }
699 | ```
700 | 
701 | ## API
702 | 
703 | ### ArrayItems
704 | 
705 | Extended attributes
706 | 
707 | | Property name | Type                      | Description     | Default value |
708 | | ------------- | ------------------------- | --------------- | ------------- |
709 | | onAdd         | `(index: number) => void` | add method      |               |
710 | | onRemove      | `(index: number) => void` | remove method   |               |
711 | | onCopy        | `(index: number) => void` | copy method     |               |
712 | | onMoveUp      | `(index: number) => void` | moveUp method   |               |
713 | | onMoveDown    | `(index: number) => void` | moveDown method |               |
714 | 
715 | Other Inherit HTMLDivElement Props
716 | 
717 | ### ArrayItems.Item
718 | 
719 | > List block
720 | 
721 | Inherit HTMLDivElement Props
722 | 
723 | Extended attributes
724 | 
725 | | Property name | Type                | Description           | Default value |
726 | | ------------- | ------------------- | --------------------- | ------------- |
727 | | type          | `'card' \|'divide'` | card or dividing line |               |
728 | 
729 | ### ArrayItems.SortHandle
730 | 
731 | > Drag handle
732 | 
733 | Reference https://ant.design/components/icon-cn/
734 | 
735 | ### ArrayItems.Addition
736 | 
737 | > Add button
738 | 
739 | Extended attributes
740 | 
741 | | Property name | Type                 | Description   | Default value |
742 | | ------------- | -------------------- | ------------- | ------------- |
743 | | title         | ReactText            | Copywriting   |               |
744 | | method        | `'push' \|'unshift'` | add method    | `'push'`      |
745 | | defaultValue  | `any`                | Default value |               |
746 | 
747 | Other references https://ant.design/components/button-cn/
748 | 
749 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
750 | 
751 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
752 | 
753 | ### ArrayItems.Copy
754 | 
755 | > Copy button
756 | 
757 | Extended attributes
758 | 
759 | | Property name | Type                 | Description | Default value |
760 | | ------------- | -------------------- | ----------- | ------------- |
761 | | title         | ReactText            | Copywriting |               |
762 | | method        | `'push' \|'unshift'` | Copy method | `'push'`      |
763 | 
764 | Other references https://ant.design/components/button-cn/
765 | 
766 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
767 | 
768 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
769 | 
770 | ### ArrayItems.Remove
771 | 
772 | > Delete button
773 | 
774 | | Property name | Type      | Description | Default value |
775 | | ------------- | --------- | ----------- | ------------- |
776 | | title         | ReactText | Copywriting |               |
777 | 
778 | Other references https://ant.design/components/icon-cn/
779 | 
780 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
781 | 
782 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
783 | 
784 | ### ArrayItems.MoveDown
785 | 
786 | > Move down button
787 | 
788 | | Property name | Type      | Description | Default value |
789 | | ------------- | --------- | ----------- | ------------- |
790 | | title         | ReactText | Copywriting |               |
791 | 
792 | Other references https://ant.design/components/icon-cn/
793 | 
794 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
795 | 
796 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
797 | 
798 | ### ArrayItems.MoveUp
799 | 
800 | > Move up button
801 | 
802 | | Property name | Type      | Description | Default value |
803 | | ------------- | --------- | ----------- | ------------- |
804 | | title         | ReactText | Copywriting |               |
805 | 
806 | Other references https://ant.design/components/icon-cn/
807 | 
808 | Note: The title attribute can receive the title mapping in the Field model, that is, uploading the title in the Field is also effective
809 | 
810 | Note: You can disable default behavior with `onClick={e => e.preventDefault()}` in props.
811 | 
812 | ### ArrayItems.Index
813 | 
814 | > Index Renderer
815 | 
816 | No attributes
817 | 
818 | ### ArrayItems.useIndex
819 | 
820 | > Read the React Hook of the current rendering row index
821 | 
822 | ### ArrayItems.useRecord
823 | 
824 | > Read the React Hook of the current rendering row
825 | 
```

--------------------------------------------------------------------------------
/packages/core/src/__tests__/array.spec.ts:
--------------------------------------------------------------------------------

```typescript
   1 | import { createForm } from '../'
   2 | import {
   3 |   onFieldValueChange,
   4 |   onFormInitialValuesChange,
   5 |   onFormValuesChange,
   6 | } from '../effects'
   7 | import { DataField } from '../types'
   8 | import { attach } from './shared'
   9 | 
  10 | test('create array field', () => {
  11 |   const form = attach(createForm())
  12 |   const array = attach(
  13 |     form.createArrayField({
  14 |       name: 'array',
  15 |     })
  16 |   )
  17 |   expect(array.value).toEqual([])
  18 |   expect(array.push).toBeDefined()
  19 |   expect(array.pop).toBeDefined()
  20 |   expect(array.shift).toBeDefined()
  21 |   expect(array.unshift).toBeDefined()
  22 |   expect(array.move).toBeDefined()
  23 |   expect(array.moveDown).toBeDefined()
  24 |   expect(array.moveUp).toBeDefined()
  25 |   expect(array.insert).toBeDefined()
  26 |   expect(array.remove).toBeDefined()
  27 | })
  28 | 
  29 | test('array field methods', () => {
  30 |   const form = attach(createForm())
  31 |   const array = attach(
  32 |     form.createArrayField({
  33 |       name: 'array',
  34 |       value: [],
  35 |     })
  36 |   )
  37 |   array.push({ aa: 11 }, { bb: 22 })
  38 |   expect(array.value).toEqual([{ aa: 11 }, { bb: 22 }])
  39 |   array.pop()
  40 |   expect(array.value).toEqual([{ aa: 11 }])
  41 |   array.unshift({ cc: 33 })
  42 |   expect(array.value).toEqual([{ cc: 33 }, { aa: 11 }])
  43 |   array.remove(1)
  44 |   expect(array.value).toEqual([{ cc: 33 }])
  45 |   array.insert(1, { dd: 44 }, { ee: 55 })
  46 |   expect(array.value).toEqual([{ cc: 33 }, { dd: 44 }, { ee: 55 }])
  47 |   array.move(0, 2)
  48 |   expect(array.value).toEqual([{ dd: 44 }, { ee: 55 }, { cc: 33 }])
  49 |   array.shift()
  50 |   expect(array.value).toEqual([{ ee: 55 }, { cc: 33 }])
  51 |   array.moveDown(0)
  52 |   expect(array.value).toEqual([{ cc: 33 }, { ee: 55 }])
  53 |   array.moveUp(1)
  54 |   expect(array.value).toEqual([{ ee: 55 }, { cc: 33 }])
  55 |   array.move(1, 0)
  56 |   expect(array.value).toEqual([{ cc: 33 }, { ee: 55 }])
  57 | })
  58 | 
  59 | test('array field children state exchanges', () => {
  60 |   //注意:插入新节点,如果指定位置有节点,会丢弃,需要重新插入节点,主要是为了防止上一个节点状态对新节点状态产生污染
  61 |   const form = attach(createForm())
  62 |   const array = attach(
  63 |     form.createArrayField({
  64 |       name: 'array',
  65 |     })
  66 |   )
  67 |   attach(
  68 |     form.createField({
  69 |       name: 'other',
  70 |       basePath: 'array',
  71 |     })
  72 |   )
  73 |   array.push({ value: 11 }, { value: 22 })
  74 |   attach(
  75 |     form.createField({
  76 |       name: 'value',
  77 |       basePath: 'array.0',
  78 |     })
  79 |   )
  80 |   attach(
  81 |     form.createField({
  82 |       name: 'value',
  83 |       basePath: 'array.1',
  84 |     })
  85 |   )
  86 |   expect(array.value).toEqual([{ value: 11 }, { value: 22 }])
  87 |   expect(form.query('array.0.value').get('value')).toEqual(11)
  88 |   expect(form.query('array.1.value').get('value')).toEqual(22)
  89 |   expect(Object.keys(form.fields).sort()).toEqual([
  90 |     'array',
  91 |     'array.0.value',
  92 |     'array.1.value',
  93 |     'array.other',
  94 |   ])
  95 |   array.pop()
  96 |   expect(array.value).toEqual([{ value: 11 }])
  97 |   expect(form.query('array.0.value').get('value')).toEqual(11)
  98 |   expect(form.query('array.1.value').get('value')).toBeUndefined()
  99 |   array.unshift({ value: 33 })
 100 |   attach(
 101 |     form.createField({
 102 |       name: 'value',
 103 |       basePath: 'array.0',
 104 |     })
 105 |   )
 106 |   attach(
 107 |     form.createField({
 108 |       name: 'value',
 109 |       basePath: 'array.1',
 110 |     })
 111 |   )
 112 |   expect(array.value).toEqual([{ value: 33 }, { value: 11 }])
 113 |   expect(form.query('array.0.value').get('value')).toEqual(33)
 114 |   expect(form.query('array.1.value').get('value')).toEqual(11)
 115 |   array.remove(1)
 116 |   expect(array.value).toEqual([{ value: 33 }])
 117 |   expect(form.query('array.0.value').get('value')).toEqual(33)
 118 |   expect(form.query('array.1.value').get('value')).toBeUndefined()
 119 |   array.insert(1, { value: 44 }, { value: 55 })
 120 |   attach(
 121 |     form.createField({
 122 |       name: 'value',
 123 |       basePath: 'array.1',
 124 |     })
 125 |   )
 126 |   attach(
 127 |     form.createField({
 128 |       name: 'value',
 129 |       basePath: 'array.2',
 130 |     })
 131 |   )
 132 |   expect(array.value).toEqual([{ value: 33 }, { value: 44 }, { value: 55 }])
 133 |   expect(form.query('array.0.value').get('value')).toEqual(33)
 134 |   expect(form.query('array.1.value').get('value')).toEqual(44)
 135 |   expect(form.query('array.2.value').get('value')).toEqual(55)
 136 |   array.move(0, 2)
 137 |   expect(array.value).toEqual([{ value: 44 }, { value: 55 }, { value: 33 }])
 138 |   expect(form.query('array.0.value').get('value')).toEqual(44)
 139 |   expect(form.query('array.1.value').get('value')).toEqual(55)
 140 |   expect(form.query('array.2.value').get('value')).toEqual(33)
 141 |   array.move(2, 0)
 142 |   expect(array.value).toEqual([{ value: 33 }, { value: 44 }, { value: 55 }])
 143 |   expect(form.query('array.0.value').get('value')).toEqual(33)
 144 |   expect(form.query('array.1.value').get('value')).toEqual(44)
 145 |   expect(form.query('array.2.value').get('value')).toEqual(55)
 146 | })
 147 | 
 148 | test('array field move up/down then fields move', () => {
 149 |   const form = attach(createForm())
 150 |   const array = attach(
 151 |     form.createArrayField({
 152 |       name: 'array',
 153 |     })
 154 |   )
 155 |   attach(
 156 |     form.createField({
 157 |       name: 'value',
 158 |       basePath: 'array.0',
 159 |     })
 160 |   )
 161 |   attach(
 162 |     form.createField({
 163 |       name: 'value',
 164 |       basePath: 'array.1',
 165 |     })
 166 |   )
 167 |   attach(
 168 |     form.createField({
 169 |       name: 'value',
 170 |       basePath: 'array.2',
 171 |     })
 172 |   )
 173 |   attach(
 174 |     form.createField({
 175 |       name: 'value',
 176 |       basePath: 'array.3',
 177 |     })
 178 |   )
 179 |   const line0 = form.fields['array.0.value']
 180 |   const line1 = form.fields['array.1.value']
 181 |   const line2 = form.fields['array.2.value']
 182 |   const line3 = form.fields['array.3.value']
 183 | 
 184 |   array.push({ value: '0' }, { value: '1' }, { value: '2' }, { value: '3' })
 185 | 
 186 |   array.move(0, 3)
 187 | 
 188 |   // 1,2,3,0
 189 |   expect(form.fields['array.0.value']).toBe(line1)
 190 |   expect(form.fields['array.1.value']).toBe(line2)
 191 |   expect(form.fields['array.2.value']).toBe(line3)
 192 |   expect(form.fields['array.3.value']).toBe(line0)
 193 | 
 194 |   array.move(3, 1)
 195 | 
 196 |   // 1,0,2,3
 197 |   expect(form.fields['array.0.value']).toBe(line1)
 198 |   expect(form.fields['array.1.value']).toBe(line0)
 199 |   expect(form.fields['array.2.value']).toBe(line2)
 200 |   expect(form.fields['array.3.value']).toBe(line3)
 201 | })
 202 | 
 203 | // 重现 issues #3932 , 补全 PR #3992 测试用例
 204 | test('lazy array field query each', () => {
 205 |   const form = attach(createForm())
 206 |   const array = attach(
 207 |     form.createArrayField({
 208 |       name: 'array',
 209 |     })
 210 |   )
 211 | 
 212 |   const init = Array.from({ length: 6 }).map((_, i) => ({ value: i }))
 213 |   array.setValue(init)
 214 | 
 215 |   // page1: 0, 1
 216 |   // page2: 2, 3 untouch
 217 |   // page3: 4, 5
 218 |   init.forEach((item) => {
 219 |     const len = item.value
 220 |     //2, 3
 221 |     if (len >= 2 && len <= 3) {
 222 |     } else {
 223 |       // 0, 1, 4, 5
 224 |       attach(
 225 |         form.createField({
 226 |           name: 'value',
 227 |           basePath: 'array.' + len,
 228 |         })
 229 |       )
 230 |     }
 231 |   })
 232 | 
 233 |   array.insert(1, { value: '11' })
 234 |   expect(() => form.query('*').take()).not.toThrowError()
 235 |   expect(Object.keys(form.fields)).toEqual([
 236 |     'array',
 237 |     'array.0.value',
 238 |     'array.5.value',
 239 |     'array.2.value',
 240 |     'array.6.value',
 241 |   ])
 242 | })
 243 | 
 244 | test('void children', () => {
 245 |   const form = attach(createForm())
 246 |   const array = attach(
 247 |     form.createArrayField({
 248 |       name: 'array',
 249 |     })
 250 |   )
 251 |   attach(
 252 |     form.createField({
 253 |       name: 'other',
 254 |       basePath: 'array',
 255 |     })
 256 |   )
 257 |   attach(
 258 |     form.createVoidField({
 259 |       name: 0,
 260 |       basePath: 'array',
 261 |     })
 262 |   )
 263 |   const aaa = attach(
 264 |     form.createField({
 265 |       name: 'aaa',
 266 |       basePath: 'array.0',
 267 |       value: 123,
 268 |     })
 269 |   )
 270 |   expect(aaa.value).toEqual(123)
 271 |   expect(array.value).toEqual([123])
 272 | })
 273 | 
 274 | test('exchange children', () => {
 275 |   const form = attach(createForm())
 276 |   const array = attach(
 277 |     form.createArrayField({
 278 |       name: 'array',
 279 |     })
 280 |   )
 281 |   attach(
 282 |     form.createField({
 283 |       name: 'other',
 284 |       basePath: 'array',
 285 |     })
 286 |   )
 287 |   attach(
 288 |     form.createField({
 289 |       name: '0.aaa',
 290 |       basePath: 'array',
 291 |       value: '123',
 292 |     })
 293 |   )
 294 |   attach(
 295 |     form.createField({
 296 |       name: '0.bbb',
 297 |       basePath: 'array',
 298 |       value: '321',
 299 |     })
 300 |   )
 301 |   attach(
 302 |     form.createField({
 303 |       name: '1.bbb',
 304 |       basePath: 'array',
 305 |       value: 'kkk',
 306 |     })
 307 |   )
 308 |   expect(array.value).toEqual([{ aaa: '123', bbb: '321' }, { bbb: 'kkk' }])
 309 |   array.move(0, 1)
 310 |   expect(array.value).toEqual([{ bbb: 'kkk' }, { aaa: '123', bbb: '321' }])
 311 |   expect(form.query('array.0.aaa').take()).toBeUndefined()
 312 | })
 313 | 
 314 | test('fault tolerance', () => {
 315 |   const form = attach(createForm())
 316 |   const array = attach(
 317 |     form.createArrayField({
 318 |       name: 'array',
 319 |     })
 320 |   )
 321 |   const array2 = attach(
 322 |     form.createArrayField({
 323 |       name: 'array2',
 324 |       value: [1, 2],
 325 |     })
 326 |   )
 327 |   array.setValue({} as any)
 328 |   array.push(11)
 329 |   expect(array.value).toEqual([11])
 330 |   array.pop()
 331 |   expect(array.value).toEqual([])
 332 |   array.remove(1)
 333 |   expect(array.value).toEqual([])
 334 |   array.shift()
 335 |   expect(array.value).toEqual([])
 336 |   array.unshift(1)
 337 |   expect(array.value).toEqual([1])
 338 |   array.move(0, 1)
 339 |   expect(array.value).toEqual([1])
 340 |   array.moveUp(1)
 341 |   expect(array.value).toEqual([1])
 342 |   array.moveDown(1)
 343 |   expect(array.value).toEqual([1])
 344 |   array.insert(1)
 345 |   expect(array.value).toEqual([1])
 346 |   array2.move(1, 1)
 347 |   expect(array2.value).toEqual([1, 2])
 348 |   array2.push(3)
 349 |   array2.moveUp(2)
 350 |   expect(array2.value).toEqual([1, 3, 2])
 351 |   array2.moveUp(0)
 352 |   expect(array2.value).toEqual([3, 2, 1])
 353 |   array2.moveDown(0)
 354 |   expect(array2.value).toEqual([2, 3, 1])
 355 |   array2.moveDown(1)
 356 |   expect(array2.value).toEqual([2, 1, 3])
 357 |   array2.moveDown(2)
 358 |   expect(array2.value).toEqual([3, 2, 1])
 359 | })
 360 | 
 361 | test('mutation fault tolerance', () => {
 362 |   const form = attach(createForm())
 363 |   const pushArray = attach(
 364 |     form.createArrayField({
 365 |       name: 'array1',
 366 |     })
 367 |   )
 368 |   const popArray = attach(
 369 |     form.createArrayField({
 370 |       name: 'array2',
 371 |     })
 372 |   )
 373 |   const insertArray = attach(
 374 |     form.createArrayField({
 375 |       name: 'array3',
 376 |     })
 377 |   )
 378 |   const removeArray = attach(
 379 |     form.createArrayField({
 380 |       name: 'array4',
 381 |     })
 382 |   )
 383 |   const shiftArray = attach(
 384 |     form.createArrayField({
 385 |       name: 'array5',
 386 |     })
 387 |   )
 388 |   const unshiftArray = attach(
 389 |     form.createArrayField({
 390 |       name: 'array6',
 391 |     })
 392 |   )
 393 |   const moveArray = attach(
 394 |     form.createArrayField({
 395 |       name: 'array7',
 396 |     })
 397 |   )
 398 |   const moveUpArray = attach(
 399 |     form.createArrayField({
 400 |       name: 'array8',
 401 |     })
 402 |   )
 403 |   const moveDownArray = attach(
 404 |     form.createArrayField({
 405 |       name: 'array9',
 406 |     })
 407 |   )
 408 |   pushArray.setValue({} as any)
 409 |   pushArray.push(123)
 410 |   expect(pushArray.value).toEqual([123])
 411 |   popArray.setValue({} as any)
 412 |   popArray.pop()
 413 |   expect(popArray.value).toEqual({})
 414 |   insertArray.setValue({} as any)
 415 |   insertArray.insert(0, 123)
 416 |   expect(insertArray.value).toEqual([123])
 417 |   removeArray.setValue({} as any)
 418 |   removeArray.remove(0)
 419 |   expect(removeArray.value).toEqual({})
 420 |   shiftArray.setValue({} as any)
 421 |   shiftArray.shift()
 422 |   expect(shiftArray.value).toEqual({})
 423 |   unshiftArray.setValue({} as any)
 424 |   unshiftArray.unshift(123)
 425 |   expect(unshiftArray.value).toEqual([123])
 426 |   moveArray.setValue({} as any)
 427 |   moveArray.move(0, 1)
 428 |   expect(moveArray.value).toEqual({})
 429 |   moveUpArray.setValue({} as any)
 430 |   moveUpArray.moveUp(0)
 431 |   expect(moveUpArray.value).toEqual({})
 432 |   moveDownArray.setValue({} as any)
 433 |   moveDownArray.moveDown(1)
 434 |   expect(moveDownArray.value).toEqual({})
 435 | })
 436 | 
 437 | test('array field move api with children', async () => {
 438 |   const form = attach(createForm())
 439 |   attach(
 440 |     form.createField({
 441 |       name: 'other',
 442 |     })
 443 |   )
 444 |   const array = attach(
 445 |     form.createArrayField({
 446 |       name: 'array',
 447 |     })
 448 |   )
 449 |   attach(
 450 |     form.createArrayField({
 451 |       name: '0',
 452 |       basePath: 'array',
 453 |     })
 454 |   )
 455 |   attach(
 456 |     form.createArrayField({
 457 |       name: '1',
 458 |       basePath: 'array',
 459 |     })
 460 |   )
 461 |   attach(
 462 |     form.createArrayField({
 463 |       name: '2',
 464 |       basePath: 'array',
 465 |     })
 466 |   )
 467 |   attach(
 468 |     form.createArrayField({
 469 |       name: 'name',
 470 |       basePath: 'array.2',
 471 |     })
 472 |   )
 473 |   await array.move(0, 2)
 474 |   expect(form.fields['array.0.name']).toBeUndefined()
 475 |   expect(form.fields['array.2.name']).toBeUndefined()
 476 |   expect(form.fields['array.1.name']).not.toBeUndefined()
 477 | })
 478 | 
 479 | test('array field remove memo leak', async () => {
 480 |   const handler = jest.fn()
 481 |   const valuesChange = jest.fn()
 482 |   const initialValuesChange = jest.fn()
 483 |   const form = attach(
 484 |     createForm({
 485 |       effects() {
 486 |         onFormValuesChange(valuesChange)
 487 |         onFormInitialValuesChange(initialValuesChange)
 488 |         onFieldValueChange('*', handler)
 489 |       },
 490 |     })
 491 |   )
 492 |   const array = attach(
 493 |     form.createArrayField({
 494 |       name: 'array',
 495 |     })
 496 |   )
 497 |   await array.push('')
 498 |   attach(
 499 |     form.createField({
 500 |       name: '0',
 501 |       basePath: 'array',
 502 |     })
 503 |   )
 504 |   await array.remove(0)
 505 |   await array.push('')
 506 |   attach(
 507 |     form.createField({
 508 |       name: '0',
 509 |       basePath: 'array',
 510 |     })
 511 |   )
 512 |   expect(handler).toBeCalledTimes(0)
 513 |   expect(valuesChange).toBeCalledTimes(4)
 514 |   expect(initialValuesChange).toBeCalledTimes(0)
 515 | })
 516 | 
 517 | test('nest array remove', async () => {
 518 |   const form = attach(createForm())
 519 | 
 520 |   const metrics = attach(
 521 |     form.createArrayField({
 522 |       name: 'metrics',
 523 |     })
 524 |   )
 525 | 
 526 |   attach(
 527 |     form.createObjectField({
 528 |       name: '0',
 529 |       basePath: 'metrics',
 530 |     })
 531 |   )
 532 | 
 533 |   attach(
 534 |     form.createObjectField({
 535 |       name: '1',
 536 |       basePath: 'metrics',
 537 |     })
 538 |   )
 539 | 
 540 |   attach(
 541 |     form.createArrayField({
 542 |       name: 'content',
 543 |       basePath: 'metrics.0',
 544 |     })
 545 |   )
 546 | 
 547 |   attach(
 548 |     form.createArrayField({
 549 |       name: 'content',
 550 |       basePath: 'metrics.1',
 551 |     })
 552 |   )
 553 | 
 554 |   const obj00 = attach(
 555 |     form.createObjectField({
 556 |       name: '0',
 557 |       basePath: 'metrics.0.content',
 558 |     })
 559 |   )
 560 | 
 561 |   const obj10 = attach(
 562 |     form.createObjectField({
 563 |       name: '0',
 564 |       basePath: 'metrics.1.content',
 565 |     })
 566 |   )
 567 | 
 568 |   attach(
 569 |     form.createField({
 570 |       name: 'attr',
 571 |       basePath: 'metrics.0.content.0',
 572 |       initialValue: '123',
 573 |     })
 574 |   )
 575 | 
 576 |   attach(
 577 |     form.createField({
 578 |       name: 'attr',
 579 |       basePath: 'metrics.1.content.0',
 580 |       initialValue: '123',
 581 |     })
 582 |   )
 583 |   expect(obj00.indexes[0]).toBe(0)
 584 |   expect(obj00.index).toBe(0)
 585 |   expect(obj10.index).toBe(0)
 586 |   expect(obj10.indexes[0]).toBe(1)
 587 |   await (form.query('metrics.1.content').take() as any).remove(0)
 588 |   expect(form.fields['metrics.0.content.0.attr']).not.toBeUndefined()
 589 |   await metrics.remove(1)
 590 |   expect(form.fields['metrics.0.content.0.attr']).not.toBeUndefined()
 591 |   expect(
 592 |     form.initialValues.metrics?.[1]?.content?.[0]?.attr
 593 |   ).not.toBeUndefined()
 594 | })
 595 | 
 596 | test('indexes: nest path need exclude incomplete number', () => {
 597 |   const form = attach(createForm())
 598 | 
 599 |   const objPathIncludeNum = attach(
 600 |     form.createField({
 601 |       name: 'attr',
 602 |       basePath: 'metrics.0.a.10.iconWidth50',
 603 |     })
 604 |   )
 605 | 
 606 |   expect(objPathIncludeNum.indexes.length).toBe(2)
 607 |   expect(objPathIncludeNum.indexes).toEqual([0, 10])
 608 |   expect(objPathIncludeNum.index).toBe(10)
 609 | })
 610 | 
 611 | test('incomplete insertion of array elements', async () => {
 612 |   const form = attach(
 613 |     createForm({
 614 |       values: {
 615 |         array: [{ aa: 1 }, { aa: 2 }, { aa: 3 }],
 616 |       },
 617 |     })
 618 |   )
 619 |   const array = attach(
 620 |     form.createArrayField({
 621 |       name: 'array',
 622 |     })
 623 |   )
 624 |   attach(
 625 |     form.createObjectField({
 626 |       name: '0',
 627 |       basePath: 'array',
 628 |     })
 629 |   )
 630 |   attach(
 631 |     form.createField({
 632 |       name: 'aa',
 633 |       basePath: 'array.0',
 634 |     })
 635 |   )
 636 |   attach(
 637 |     form.createObjectField({
 638 |       name: '2',
 639 |       basePath: 'array',
 640 |     })
 641 |   )
 642 |   attach(
 643 |     form.createField({
 644 |       name: 'aa',
 645 |       basePath: 'array.2',
 646 |     })
 647 |   )
 648 |   expect(form.fields['array.0.aa']).not.toBeUndefined()
 649 |   expect(form.fields['array.1.aa']).toBeUndefined()
 650 |   expect(form.fields['array.2.aa']).not.toBeUndefined()
 651 |   await array.unshift({})
 652 |   expect(form.fields['array.0.aa']).toBeUndefined()
 653 |   expect(form.fields['array.1.aa']).not.toBeUndefined()
 654 |   expect(form.fields['array.2.aa']).toBeUndefined()
 655 |   expect(form.fields['array.3.aa']).not.toBeUndefined()
 656 | })
 657 | 
 658 | test('void array items need skip data', () => {
 659 |   const form = attach(createForm())
 660 |   const array = attach(
 661 |     form.createArrayField({
 662 |       name: 'array',
 663 |     })
 664 |   )
 665 |   const array2 = attach(
 666 |     form.createArrayField({
 667 |       name: 'array2',
 668 |     })
 669 |   )
 670 |   attach(
 671 |     form.createVoidField({
 672 |       name: '0',
 673 |       basePath: 'array',
 674 |     })
 675 |   )
 676 |   attach(
 677 |     form.createVoidField({
 678 |       name: '0',
 679 |       basePath: 'array2',
 680 |     })
 681 |   )
 682 |   attach(
 683 |     form.createVoidField({
 684 |       name: 'space',
 685 |       basePath: 'array.0',
 686 |     })
 687 |   )
 688 |   const select = attach(
 689 |     form.createField({
 690 |       name: 'select',
 691 |       basePath: 'array.0.space',
 692 |     })
 693 |   )
 694 |   const select2 = attach(
 695 |     form.createField({
 696 |       name: 'select2',
 697 |       basePath: 'array2.0',
 698 |     })
 699 |   )
 700 | 
 701 |   select.value = 123
 702 |   select2.value = 123
 703 |   expect(array.value).toEqual([123])
 704 |   expect(array2.value).toEqual([123])
 705 | })
 706 | 
 707 | test('array field reset', () => {
 708 |   const form = attach(createForm())
 709 |   const array = attach(
 710 |     form.createArrayField({
 711 |       name: 'array',
 712 |     })
 713 |   )
 714 |   attach(
 715 |     form.createObjectField({
 716 |       name: '0',
 717 |       basePath: 'array',
 718 |     })
 719 |   )
 720 |   attach(
 721 |     form.createField({
 722 |       name: 'input',
 723 |       initialValue: '123',
 724 |       basePath: 'array.0',
 725 |     })
 726 |   )
 727 |   form.reset('*', { forceClear: true })
 728 |   expect(form.values).toEqual({ array: [] })
 729 |   expect(array.value).toEqual([])
 730 | })
 731 | 
 732 | test('array field remove can not memory leak', async () => {
 733 |   const handler = jest.fn()
 734 |   const form = attach(
 735 |     createForm({
 736 |       values: {
 737 |         array: [{ aa: 1 }, { aa: 2 }],
 738 |       },
 739 |       effects() {
 740 |         onFieldValueChange('array.*.aa', handler)
 741 |       },
 742 |     })
 743 |   )
 744 |   const array = attach(
 745 |     form.createArrayField({
 746 |       name: 'array',
 747 |     })
 748 |   )
 749 |   attach(
 750 |     form.createObjectField({
 751 |       name: '0',
 752 |       basePath: 'array',
 753 |     })
 754 |   )
 755 |   attach(
 756 |     form.createField({
 757 |       name: 'aa',
 758 |       basePath: 'array.0',
 759 |     })
 760 |   )
 761 |   attach(
 762 |     form.createObjectField({
 763 |       name: '1',
 764 |       basePath: 'array',
 765 |     })
 766 |   )
 767 |   attach(
 768 |     form.createField({
 769 |       name: 'aa',
 770 |       basePath: 'array.1',
 771 |     })
 772 |   )
 773 |   const bb = attach(
 774 |     form.createField({
 775 |       name: 'bb',
 776 |       basePath: 'array.1',
 777 |       reactions: (field) => {
 778 |         field.visible = field.query('.aa').value() === '123'
 779 |       },
 780 |     })
 781 |   )
 782 |   expect(bb.visible).toBeFalsy()
 783 |   await array.remove(0)
 784 |   form.query('array.0.aa').take((field) => {
 785 |     ;(field as DataField).value = '123'
 786 |   })
 787 |   expect(bb.visible).toBeTruthy()
 788 |   expect(handler).toBeCalledTimes(1)
 789 | })
 790 | 
 791 | test('array field patch values', async () => {
 792 |   const form = attach(createForm())
 793 | 
 794 |   const arr = attach(
 795 |     form.createArrayField({
 796 |       name: 'a',
 797 |     })
 798 |   )
 799 | 
 800 |   await arr.unshift({})
 801 |   attach(
 802 |     form.createObjectField({
 803 |       name: '0',
 804 |       basePath: 'a',
 805 |     })
 806 |   )
 807 |   attach(
 808 |     form.createField({
 809 |       name: 'c',
 810 |       initialValue: 'A',
 811 |       basePath: 'a.0',
 812 |     })
 813 |   )
 814 |   expect(form.values).toEqual({ a: [{ c: 'A' }] })
 815 |   await arr.unshift({})
 816 |   attach(
 817 |     form.createObjectField({
 818 |       name: '0',
 819 |       basePath: 'a',
 820 |     })
 821 |   )
 822 |   attach(
 823 |     form.createField({
 824 |       name: 'c',
 825 |       initialValue: 'A',
 826 |       basePath: 'a.0',
 827 |     })
 828 |   )
 829 |   attach(
 830 |     form.createObjectField({
 831 |       name: '1',
 832 |       basePath: 'a',
 833 |     })
 834 |   )
 835 |   attach(
 836 |     form.createField({
 837 |       name: 'c',
 838 |       initialValue: 'A',
 839 |       basePath: 'a.1',
 840 |     })
 841 |   )
 842 |   expect(form.values).toEqual({ a: [{ c: 'A' }, { c: 'A' }] })
 843 | })
 844 | 
 845 | test('array remove with initialValues', async () => {
 846 |   const form = attach(
 847 |     createForm({
 848 |       initialValues: {
 849 |         array: [{ a: 1 }, { a: 2 }],
 850 |       },
 851 |     })
 852 |   )
 853 |   const array = attach(
 854 |     form.createArrayField({
 855 |       name: 'array',
 856 |     })
 857 |   )
 858 |   attach(
 859 |     form.createObjectField({
 860 |       name: '0',
 861 |       basePath: 'array',
 862 |     })
 863 |   )
 864 |   attach(
 865 |     form.createObjectField({
 866 |       name: '1',
 867 |       basePath: 'array',
 868 |     })
 869 |   )
 870 |   attach(
 871 |     form.createField({
 872 |       name: 'a',
 873 |       basePath: 'array.0',
 874 |     })
 875 |   )
 876 |   attach(
 877 |     form.createField({
 878 |       name: 'a',
 879 |       basePath: 'array.1',
 880 |     })
 881 |   )
 882 |   expect(form.values).toEqual({ array: [{ a: 1 }, { a: 2 }] })
 883 |   await array.remove(1)
 884 |   expect(form.values).toEqual({ array: [{ a: 1 }] })
 885 |   expect(form.initialValues).toEqual({ array: [{ a: 1 }, { a: 2 }] })
 886 |   await array.reset()
 887 |   attach(
 888 |     form.createObjectField({
 889 |       name: '1',
 890 |       basePath: 'array',
 891 |     })
 892 |   )
 893 |   attach(
 894 |     form.createField({
 895 |       name: 'a',
 896 |       basePath: 'array.0',
 897 |     })
 898 |   )
 899 |   attach(
 900 |     form.createField({
 901 |       name: 'a',
 902 |       basePath: 'array.1',
 903 |     })
 904 |   )
 905 |   expect(form.values).toEqual({ array: [{ a: 1 }, { a: 2 }] })
 906 |   expect(form.initialValues).toEqual({ array: [{ a: 1 }, { a: 2 }] })
 907 | })
 908 | 
 909 | test('records: find array fields', () => {
 910 |   const form = attach(
 911 |     createForm({
 912 |       initialValues: {
 913 |         array: [{ a: 1 }, { a: 2 }],
 914 |       },
 915 |     })
 916 |   )
 917 | 
 918 |   attach(
 919 |     form.createArrayField({
 920 |       name: 'array',
 921 |     })
 922 |   )
 923 | 
 924 |   attach(
 925 |     form.createObjectField({
 926 |       name: '0',
 927 |       basePath: 'array',
 928 |     })
 929 |   )
 930 |   attach(
 931 |     form.createObjectField({
 932 |       name: '1',
 933 |       basePath: 'array',
 934 |     })
 935 |   )
 936 |   const field0 = attach(
 937 |     form.createField({
 938 |       name: 'a',
 939 |       basePath: 'array.0',
 940 |     })
 941 |   )
 942 |   const field1 = attach(
 943 |     form.createField({
 944 |       name: 'a',
 945 |       basePath: 'array.1',
 946 |     })
 947 |   )
 948 | 
 949 |   expect(field0.records.length).toBe(2)
 950 |   expect(field0.record).toEqual({ a: 1 })
 951 |   expect(field1.record).toEqual({ a: 2 })
 952 | })
 953 | 
 954 | test('record: find array nest field record', () => {
 955 |   const form = attach(
 956 |     createForm({
 957 |       initialValues: {
 958 |         array: [{ a: { b: { c: 1, d: 1 } } }, { a: { b: { c: 2, d: 2 } } }],
 959 |       },
 960 |     })
 961 |   )
 962 | 
 963 |   attach(
 964 |     form.createArrayField({
 965 |       name: 'array',
 966 |     })
 967 |   )
 968 | 
 969 |   attach(
 970 |     form.createObjectField({
 971 |       name: '0',
 972 |       basePath: 'array',
 973 |     })
 974 |   )
 975 |   attach(
 976 |     form.createObjectField({
 977 |       name: '1',
 978 |       basePath: 'array',
 979 |     })
 980 |   )
 981 | 
 982 |   attach(
 983 |     form.createObjectField({
 984 |       name: 'a',
 985 |       basePath: 'array.0',
 986 |     })
 987 |   )
 988 |   attach(
 989 |     form.createObjectField({
 990 |       name: 'a',
 991 |       basePath: 'array.1',
 992 |     })
 993 |   )
 994 | 
 995 |   attach(
 996 |     form.createObjectField({
 997 |       name: 'b',
 998 |       basePath: 'array.0.a',
 999 |     })
1000 |   )
1001 | 
1002 |   attach(
1003 |     form.createObjectField({
1004 |       name: 'b',
1005 |       basePath: 'array.1.a',
1006 |     })
1007 |   )
1008 | 
1009 |   const field0 = attach(
1010 |     form.createField({
1011 |       name: 'c',
1012 |       basePath: 'array.0.a.b',
1013 |     })
1014 |   )
1015 | 
1016 |   const field1 = attach(
1017 |     form.createField({
1018 |       name: 'c',
1019 |       basePath: 'array.1.a.b',
1020 |     })
1021 |   )
1022 | 
1023 |   const field2 = attach(
1024 |     form.createField({
1025 |       name: 'cc',
1026 |       basePath: 'array.1.a.b.c',
1027 |     })
1028 |   )
1029 | 
1030 |   expect(field0.records.length).toBe(2)
1031 |   expect(field1.records.length).toBe(2)
1032 |   expect(field1.records).toEqual([
1033 |     { a: { b: { c: 1, d: 1 } } },
1034 |     { a: { b: { c: 2, d: 2 } } },
1035 |   ])
1036 |   expect(field0.record).toEqual({ c: 1, d: 1 })
1037 |   expect(field1.record).toEqual({ c: 2, d: 2 })
1038 |   expect(field2.record).toEqual({ c: 2, d: 2 })
1039 | })
1040 | 
1041 | test('record: find array field record', () => {
1042 |   const form = attach(
1043 |     createForm({
1044 |       initialValues: {
1045 |         array: [1, 2, 3],
1046 |       },
1047 |     })
1048 |   )
1049 | 
1050 |   attach(
1051 |     form.createArrayField({
1052 |       name: 'array',
1053 |     })
1054 |   )
1055 | 
1056 |   const field = attach(
1057 |     form.createField({
1058 |       basePath: 'array',
1059 |       name: '0',
1060 |     })
1061 |   )
1062 | 
1063 |   expect(field.records.length).toBe(3)
1064 |   expect(field.record).toEqual(1)
1065 | })
1066 | 
1067 | test('record: find object field record', () => {
1068 |   const form = attach(
1069 |     createForm({
1070 |       initialValues: {
1071 |         a: {
1072 |           b: {
1073 |             c: 1,
1074 |             d: 1,
1075 |           },
1076 |         },
1077 |       },
1078 |     })
1079 |   )
1080 | 
1081 |   attach(
1082 |     form.createArrayField({
1083 |       name: 'a',
1084 |     })
1085 |   )
1086 | 
1087 |   attach(
1088 |     form.createObjectField({
1089 |       name: 'b',
1090 |       basePath: 'a',
1091 |     })
1092 |   )
1093 | 
1094 |   const fieldc = attach(
1095 |     form.createObjectField({
1096 |       name: 'c',
1097 |       basePath: 'a.b',
1098 |     })
1099 |   )
1100 | 
1101 |   expect(fieldc.records).toEqual(undefined)
1102 |   expect(fieldc.record).toEqual({
1103 |     c: 1,
1104 |     d: 1,
1105 |   })
1106 | })
1107 | 
1108 | test('record: find form fields', () => {
1109 |   const form = attach(
1110 |     createForm({
1111 |       initialValues: {
1112 |         array: [{ a: 1 }, { a: 2 }],
1113 |       },
1114 |     })
1115 |   )
1116 | 
1117 |   const array = attach(
1118 |     form.createArrayField({
1119 |       name: 'array',
1120 |     })
1121 |   )
1122 | 
1123 |   expect(array.record).toEqual({ array: [{ a: 1 }, { a: 2 }] })
1124 | })
1125 | 
```

--------------------------------------------------------------------------------
/docs/guide/index.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Introduction
  2 | 
  3 | ## Problem
  4 | 
  5 | As we all know, the form scene has always been the most complex scene in the front-end and back-end fields. What is the main complexity of it?
  6 | 
  7 | - There are a lot of fields, how can the performance not deteriorate with the increase of the number of fields?
  8 | - Field association logic is complex, how to implement complex linkage logic more simply? How to ensure that the form performance is not affected when the field is associated with the field?
  9 | 
 10 |   - One-to-Many (asynchronous)
 11 |   - Many-to-One (asynchronous)
 12 |   - Many-to-Many (asynchronous)
 13 | 
 14 | - Complex form data management
 15 |   - Form value conversion logic is complex (front and back formats are inconsistent)
 16 |   - The logic of merging synchronous and asynchronous default values is complicated
 17 |   - Cross-form data communication, how to keep the performance from deteriorating with the increase in the number of fields?
 18 | - Complex form state management
 19 |   - Focusing on the self-incrementing list scenario, how to make the array data move, and the field status can follow the move during the deletion process?
 20 | - Scene reuse of forms
 21 |   - Query list
 22 |   - Dialog/Drawer form
 23 |   - Step form
 24 |   - Tab form
 25 | - Dynamic rendering requirements are very strong
 26 |   - Field configuration allows non-professional front-ends to quickly build complex forms
 27 |   - Cross-terminal rendering, a JSON Schema, multi-terminal adaptation
 28 |   - How to describe the layout in the form protocol?
 29 |     - Vertical layout
 30 |     - Horizontal layout
 31 |     - Grid layout
 32 |     - Flexible layout
 33 |     - Free layout
 34 |   - How to describe the logic in the form protocol?
 35 | 
 36 | So many problems, how to solve them, think about it, But we still have to find a solution,Not only to solve but also to solve elegantly, The Alibaba digital supply chain team, after experiencing a lot of middle and back-office practice and exploration, finally precipitated **Formily form solution**. All the problems mentioned above, after going through UForm to Formily1.x, until Formily2.x finally achieved the degree of **elegant solution**. So how does Formily 2.x solve these problems?
 37 | 
 38 | ## Solution
 39 | 
 40 | In order to solve the above problems, we can further refine the problem and come up with a breakthrough direction.
 41 | 
 42 | ### Accurate Rendering
 43 | 
 44 | In the React scenario, to realize a form requirement, most of them use setState to realize field data collection. because form data needs to be collected and some linkage requirements are realized.This implementation is very simple and the mental cost is very low, but it also introduces performance problems, because each input will cause all fields to be rendered in full. Although there is diff at the DOM update level, diff also has a computational cost, which wastes a lot of computational resources. In terms of time complexity, the initial rendering of the form is O(n), and the field input is also O(n), which is obviously unreasonable.
 45 | 
 46 | Historical experience is always helpful to mankind. Decades ago, humans created the MVVM design pattern. The core of this design pattern is to abstract the view model and consume it at the DSL template layer.SL uses a certain dependency collection mechanism, and then uniformly schedules in the view model to ensure that each input is accurately rendered. This is the industrial-grade GUI form!
 47 | 
 48 | It just so happened that the github community abstracted a state management solution called Mobx for such MVVM models. The core capabilities of [Mobx](https://github.com/mobxjs/mobx) are its dependency tracking mechanism and the abstraction capabilities of responsive models.
 49 | 
 50 | Therefore, with the help of Mobx, the O(n) problem in the form field input process can be completely solved, and it can be solved very elegantly. However, during the implementation of Formily 2.x, it was discovered that Mobx still has some problems that are not compatible with Formily's core ideas. In the end, we only can reinvent one wheel,[@formily/reactive](https://reactive.formilyjs.org) which continues the core idea of Mobx.
 51 | 
 52 | Mention here [react-hook-form](https://github.com/react-hook-form/react-hook-form) , Very popular, known as the industry’s top performance form solution, let’s take a look at its simplest case:
 53 | 
 54 | ```tsx pure
 55 | import React from 'react'
 56 | import ReactDOM from 'react-dom'
 57 | import { useForm } from 'react-hook-form'
 58 | 
 59 | function App() {
 60 |   const { register, handleSubmit, errors } = useForm() // initialize the hook
 61 |   const onSubmit = (data) => {
 62 |     console.log(data)
 63 |   }
 64 | 
 65 |   return (
 66 |     <form onSubmit={handleSubmit(onSubmit)}>
 67 |       <input name="firstname" ref={register} /> {/* register an input */}
 68 |       <input name="lastname" ref={register({ required: true })} />
 69 |       {errors.lastname && 'Last name is required.'}
 70 |       <input name="age" ref={register({ pattern: /\d+/ })} />
 71 |       {errors.age && 'Please enter number for age.'}
 72 |       <input type="submit" />
 73 |     </form>
 74 |   )
 75 | }
 76 | 
 77 | ReactDOM.render(<App />, document.getElementById('root'))
 78 | ```
 79 | 
 80 | Although the value management achieves accurate rendering, when the verification is triggered, the form will still be rendered in full. Because of the update of the errors state, the overall controlled rendering is necessary to achieve synchronization. This is only the full rendering of the verification meeting. In fact, there is linkage. To achieve linkage with react-hook-form, it also requires overall controlled rendering to achieve linkage. Therefore, if you want to truly achieve accurate rendering, it must be Reactive!
 81 | 
 82 | ### Domain Model
 83 | 
 84 | As mentioned in the previous question, the linkage of forms is very complicated, including various relationships between fields. Let’s imagine that most form linkages are basically linkages triggered based on the values of certain fields. However, actual business requirements may be sophisticated. It is not only necessary to trigger linkage based on certain field values, but also based on other side-effect values, such as application status, server data status, page URL, internal data of a UI component of a field, and current Other data status of the field itself, some special asynchronous events, etc. Use a picture to describe:
 85 | 
 86 | ![image-20210202081316031](//img.alicdn.com/imgextra/i3/O1CN01LWjBSt251w5BtGHW2_!!6000000007467-55-tps-1100-432.svg)
 87 | 
 88 | As you can see from the above figure, in order to achieve a linkage relationship, the core is to associate certain state attributes of the field with certain data. Some data here can be external data or own data. For example, the display/hide of a field is associated with certain data, the value of a field is associated with certain data, and the disabling/editing of a field is associated with certain data. Here are three examples. We have actually abstracted it. One of the simplest Field model:
 89 | 
 90 | ```typescript
 91 | interface Field {
 92 |   value: any
 93 |   visible: boolean
 94 |   disabled: boolean
 95 | }
 96 | ```
 97 | 
 98 | Of course, does the Field model only have these 3 attributes? Definitely not, if we want to express a field, then the path of the field must have, Because we want to describe the entire form tree structure, at the same time, we also need to manage the properties of the field corresponding to the UI component. For example, Input and Select have their properties. For example, the placeholder of Input is associated with some data, or the drop-down option of Select is associated with some data, so you can understand it. So, our Field model can look like this:
 99 | 
100 | ```typescript
101 | interface Field {
102 |   path: string[]
103 |   value: any
104 |   visible: boolean
105 |   disabled: boolean
106 |   component: [Component, ComponentProps]
107 | }
108 | ```
109 | 
110 | We have added the component attribute, which represents the UI component and UI component attribute corresponding to the field, so that the ability to associate certain data with the field component attribute, or even the field component, is realized. Are there any more? Of course, there are also, such as the outer package container of the field, usually we call it FormItem, which is mainly responsible for the interactive style of the field, such as the field title, the style of error prompts, etc., If we want to include more linkage, such as the linkage between certain data and FormItem, then we have to add the outer package container. There are many other attributes, which are not listed here.
111 | 
112 | From the above ideas, we can see that in order to solve the linkage problem, no matter how abstract we are, the field model will eventually be abstracted. It contains all the states related to the field. As long as these states are manipulated, linkage can be triggered.
113 | 
114 | Regarding accurate rendering, we have determined that we can choose a Reactive solution similar to Mobx. Although it is a reinvention of a wheel, the Reactive model is still very suitable for abstract responsive models. So based on the ability of Reactive, Formily, after constant trial and error and correction, finally designed a truly elegant form model. Such a form model solves the problem of the form domain, so it is also called a domain model. With such a domain model, we can make the linkage of the form enumerable and predictable, which also lays a solid foundation for the linkage of the protocol description to be discussed later.
115 | 
116 | ### Path System
117 | 
118 | The field model in the form domain model was mentioned earlier. If the design is more complete, it is not only a field model, but also a form model as the top-level model. The top-level model manages all the field models, and each field has its own Path. How to find these fields? The linkage relationship mentioned earlier is more of a passive dependency, but in some scenarios, we just need to modify the state of a field based on an asynchronous event action. Here is how to find a field elegantly. The same It has also undergone a lot of trial and error and correction. Formily's original path system @formily/path solves this problem very well. It not only makes the field lookup elegant, but it can also deal with the disgusting problem of inconsistent front-end and back-end data structures through destructuring expressions.
119 | 
120 | ### Life Cycle
121 | 
122 | With the help of Mobx and the path system, we have created a relatively complete form scheme, but after this abstraction, our scheme is like a black box, and the outside world cannot perceive the internal state flow process of the scheme. If you want to implement some logic in a certain process stage, you cannot achieve it. So, here we need another concept, the life cycle. As long as we expose the entire form life cycle as an event hook to the outside world, we can achieve an abstract but flexible form solution.
123 | 
124 | ### Protocol Driven
125 | 
126 | If you want to implement a dynamically configurable form, you must make the form structure serializable.
127 | There are many ways to serialize, which can be a UI description protocol based on the UI, or a data description protocol based on the data. Because the form itself is to maintain a copy of data, it is natural that for the form scenario, the data protocol is the most suitable. To describe the data structure, [JSON-Schema](https://json-schema.org/) is now the most popular in the industry. Because the JSON Schema protocol itself has many verification-related attributes, this is naturally associated with form verification. Is the UI description protocol really not suitable for describing forms? No, the UI description protocol is suitable for more general UI expressions. Of course, the description form is not a problem, but it will be more front-end protocol. On the contrary, JSON-Schema is expressible at the back-end model layer, and is more versatile in describing data. Therefore, the two protocols have their own strengths, but in the field of pure forms, JSON-Schema will be more domain-oriented.
128 | 
129 | So, if we choose JSON-Schema, how do we describe the UI and how do we describe the logic? It is not realistic to simply describe the data and output the form pages available for actual business.
130 | 
131 | The solution of [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form) is that data is data and UI is UI. The advantage of this is that each protocol is a very pure protocol, but it brings a large maintenance cost and understanding cost.
132 | To develop a form, users need to constantly switch between the two protocols mentally. Therefore, if you look at such a split from a technical perspective, it is very reasonable, but from a product perspective, the split is to throw the cost to the user. Therefore, Formily's form protocol will be more inclined to expand on JSON-Schema.
133 | 
134 | So, how to expand? In order not to pollute the standard JSON-Schema attributes, we uniformly express the extended attributes in the x-\* format:
135 | 
136 | ```json
137 | {
138 |   "type": "string",
139 |   "title": "String",
140 |   "description": "This is a string",
141 |   "x-component": "Input",
142 |   "x-component-props": {
143 |     "placeholder": "please enter"
144 |   }
145 | }
146 | ```
147 | 
148 | In this way, the UI protocol and the data protocol are mixed together. As long as there is a unified extension agreement, the responsibilities of the two protocols can still be guaranteed to be single.
149 | 
150 | Then, what if you want to wrap a UI container on certain fields? Here, Formily defines a new schema type called `void`. No stranger to void, there is also void element in W3C specification, and void keyword in js. The former represents virtual elements, and the latter represents virtual pointers. Therefore, in JSON Schema, void is introduced to represent a virtual data node, which means that the node does not occupy the actual data structure. So, we can do this:
151 | 
152 | ```json
153 | {
154 |   "type": "void",
155 |   "title": "card",
156 |   "description": "This is a card",
157 |   "x-component": "Card",
158 |   "properties": {
159 |     "string": {
160 |       "type": "string",
161 |       "title": "String",
162 |       "description": "This is a string",
163 |       "x-component": "Input",
164 |       "x-component-props": {
165 |         "placeholder": "please enter"
166 |       }
167 |     }
168 |   }
169 | }
170 | ```
171 | 
172 | In this way, a UI container can be described. Because the UI container can be described, we can easily encapsulate a scene-based component, such as FormStep. So how do we describe the linkage between fields? For example, one field needs to control the display and hide of another field. We can do this:
173 | 
174 | ```json
175 | {
176 |   "type": "object",
177 |   "properties": {
178 |     "source": {
179 |       "type": "string",
180 |       "title": "Source",
181 |       "x-component": "Input",
182 |       "x-component-props": {
183 |         "placeholder": "please enter"
184 |       }
185 |     },
186 |     "target": {
187 |       "type": "string",
188 |       "title": "Target",
189 |       "x-component": "Input",
190 |       "x-component-props": {
191 |         "placeholder": "please enter"
192 |       },
193 |       "x-reactions": [
194 |         {
195 |           "dependencies": ["source"],
196 |           "when": "{{$deps[0] == '123'}}",
197 |           "fulfill": {
198 |             "state": {
199 |               "visible": true
200 |             }
201 |           },
202 |           "otherwise": {
203 |             "state": {
204 |               "visible": false
205 |             }
206 |           }
207 |         }
208 |       ]
209 |     }
210 |   }
211 | }
212 | ```
213 | 
214 | The target field is described with the help of `x-reactions`, which depends on the value of the source field. If the value is `'123'`, the target field is displayed, otherwise it is hidden. This linkage method is a passive linkage. What if we want to achieve active linkage ? It can be like this:
215 | 
216 | ```json
217 | {
218 |   "type": "object",
219 |   "properties": {
220 |     "source": {
221 |       "type": "string",
222 |       "title": "Source",
223 |       "x-component": "Input",
224 |       "x-component-props": {
225 |         "placeholder": "please enter"
226 |       },
227 |       "x-reactions": [
228 |         {
229 |           "when": "{{$self.value == '123'}}",
230 |           "target": "target",
231 |           "fulfill": {
232 |             "state": {
233 |               "visible": true
234 |             }
235 |           },
236 |           "otherwise": {
237 |             "state": {
238 |               "visible": false
239 |             }
240 |           }
241 |         }
242 |       ]
243 |     },
244 |     "target": {
245 |       "type": "string",
246 |       "title": "Target",
247 |       "x-component": "Input",
248 |       "x-component-props": {
249 |         "placeholder": "please enter"
250 |       }
251 |     }
252 |   }
253 | }
254 | ```
255 | 
256 | Just change the location of `x-reactions`, put it on the source field, and then specify a target.
257 | 
258 | It can be seen that our linkage is actually based on:
259 | 
260 | - condition
261 | - Condition-satisfied action
262 | - Unsatisfied action
263 | 
264 | To achieve. Because the internal state management uses the [@formily/reactive](https://reactive.formilyjs.org) solution similar to Mobx, Formily easily realizes passive and active linkage scenarios, covering most business needs.
265 | 
266 | Therefore, our form can be described by protocol, and it can be configurable no matter how complicated the layout is or the linkage is very complicated.
267 | 
268 | ### Layered Architecture
269 | 
270 | I talked about the solutions to various problems at the beginning, so how do we design now to make Formily more self-consistent and elegant?
271 | 
272 | ![](https://img.alicdn.com/imgextra/i4/O1CN019qbf1b1ChnTfT9x3X_!!6000000000113-55-tps-1939-1199.svg)
273 | 
274 | This picture mainly divides Formily into the kernel layer, UI bridge layer, extended component layer, and configuration application layer.
275 | 
276 | The kernel layer is UI-independent. It ensures that the logic and state of user management are not coupled to any framework. This has several advantages:
277 | 
278 | - Logic and UI framework are decoupled, and framework-level migration will be done in the future, without extensive refactoring of business code.
279 | - The learning cost is uniform. If the user uses @formily/react, the business will be migrated to @formily/vue in the future, and the user does not need to learn again.
280 | 
281 | JSON Schema exists independently and is consumed by the UI bridging layer, ensuring the absolute consistency of protocol drivers under different UI frameworks, and there is no need to repeatedly implement protocol parsing logic.
282 | 
283 | Extend the component layer to provide a series of form scene components to ensure that users can use it out of the box. No need to spend a lot of time for secondary development.
284 | 
285 | ## Competitive Product Comparison
286 | 
287 | ```tsx
288 | /**
289 |  * inline: true
290 |  */
291 | import React from 'react'
292 | import { Table, Tooltip } from 'antd'
293 | import { QuestionCircleOutlined } from '@ant-design/icons'
294 | 
295 | const text = (content, tooltips) => {
296 |   if (tooltips) {
297 |     return (
298 |       <div>
299 |         {content}
300 |         <Tooltip title={tooltips}>
301 |           <QuestionCircleOutlined style={{ marginLeft: 3 }} />
302 |         </Tooltip>
303 |       </div>
304 |     )
305 |   }
306 |   return content
307 | }
308 | 
309 | const dataSource = [
310 |   {
311 |     feature: 'Custom component access cost',
312 |     antd: '4.x low access cost',
313 |     fusion: 'high',
314 |     formik: 'low',
315 |     finalForm: 'low',
316 |     schemaForm: text('high', 'Because of coupling bootstrap'),
317 |     hookForm: text('high', 'Because of coupling React Ref'),
318 |     'formily1.x': 'low',
319 |     'formily2.x': 'low',
320 |   },
321 |   {
322 |     feature: 'performance',
323 |     antd: text(
324 |       '4.x performance is better',
325 |       'Only solved the value synchronization and accurate rendering'
326 |     ),
327 |     fusion: 'bad',
328 |     formik: 'bad',
329 |     finalForm: text(
330 |       'better',
331 |       'But only solved the value synchronization and accurate rendering'
332 |     ),
333 |     schemaForm: 'bad',
334 |     hookForm: text(
335 |       'good',
336 |       'But only solved the value synchronization and accurate rendering'
337 |     ),
338 |     'formily1.x': text(
339 |       'excellent',
340 |       'Can solve the precise rendering in the linkage process'
341 |     ),
342 |     'formily2.x': text(
343 |       'excellent',
344 |       'Can solve the precise rendering in the linkage process'
345 |     ),
346 |   },
347 |   {
348 |     feature: 'Whether to support dynamic rendering',
349 |     antd: 'no',
350 |     fusion: 'no',
351 |     formik: 'no',
352 |     finalForm: 'no',
353 |     schemaForm: 'yes',
354 |     hookForm: 'no',
355 |     'formily1.x': 'yes',
356 |     'formily2.x': 'yes',
357 |   },
358 |   {
359 |     feature: 'Whether to use out of the box',
360 |     antd: 'yes',
361 |     fusion: 'yes',
362 |     formik: 'no',
363 |     finalForm: 'no',
364 |     schemaForm: 'yes',
365 |     hookForm: 'no',
366 |     'formily1.x': 'yes',
367 |     'formily2.x': 'yes',
368 |   },
369 |   {
370 |     feature: 'Whether to support cross-terminal',
371 |     antd: 'no',
372 |     fusion: 'no',
373 |     formik: 'no',
374 |     finalForm: 'no',
375 |     schemaForm: 'no',
376 |     hookForm: 'no',
377 |     'formily1.x': 'yes',
378 |     'formily2.x': 'yes',
379 |   },
380 |   {
381 |     feature: 'Development efficiency',
382 |     antd: 'general',
383 |     fusion: 'generalv',
384 |     formik: 'general',
385 |     finalForm: 'general',
386 |     schemaForm: text(
387 |       'low',
388 |       'Source code development requires manual maintenance of JSON'
389 |     ),
390 |     hookForm: 'general',
391 |     'formily1.x': 'high',
392 |     'formily2.x': 'high',
393 |   },
394 |   {
395 |     feature: 'Learning cost',
396 |     antd: 'easy',
397 |     fusion: 'easy',
398 |     formik: 'easy',
399 |     finalForm: 'hard',
400 |     schemaForm: 'hard',
401 |     hookForm: 'easy',
402 |     'formily1.x': 'very hard',
403 |     'formily2.x': text('hard', 'The concept is drastically reduced'),
404 |   },
405 |   {
406 |     feature: 'View code maintainability',
407 |     antd: text('bad', 'Lots of conditional expressions'),
408 |     fusion: text('bad', 'Lots of conditional expressions'),
409 |     formik: text('bad', 'Lots of conditional expressions'),
410 |     finalForm: text('bad', 'Lots of conditional expressions'),
411 |     schemaForm: 'good',
412 |     hookForm: text('bad', 'Lots of conditional expressions'),
413 |     'formily1.x': 'good',
414 |     'formily2.x': 'good',
415 |   },
416 |   {
417 |     feature: 'Scenario-based packaging capabilities',
418 |     antd: 'no',
419 |     fusion: 'no',
420 |     formik: 'no',
421 |     finalForm: 'no',
422 |     schemaForm: 'yes',
423 |     hookForm: 'no',
424 |     'formily1.x': 'yes',
425 |     'formily2.x': 'yes',
426 |   },
427 |   {
428 |     feature: 'Whether to support form preview',
429 |     antd: 'no',
430 |     fusion: 'yes',
431 |     formik: 'no',
432 |     finalForm: 'no',
433 |     schemaForm: 'no',
434 |     hookForm: 'no',
435 |     'formily1.x': 'yes',
436 |     'formily2.x': 'yes',
437 |   },
438 | ]
439 | 
440 | export default () => {
441 |   return (
442 |     <Table
443 |       dataSource={dataSource}
444 |       pagination={false}
445 |       bordered
446 |       scroll={{ x: 1600 }}
447 |       size="small"
448 |     >
449 |       <Table.Column title="ability" dataIndex="feature" width={160} />
450 |       <Table.Column title="Ant Design Form" dataIndex="antd" width={160} />
451 |       <Table.Column title="Fusion Form" dataIndex="fusion" width={160} />
452 |       <Table.Column title="Formik" dataIndex="formik" width={160} />
453 |       <Table.Column
454 |         title="React Final Form"
455 |         dataIndex="finalForm"
456 |         width={160}
457 |       />
458 |       <Table.Column
459 |         title="React Schema Form"
460 |         dataIndex="schemaForm"
461 |         width={160}
462 |       />
463 |       <Table.Column title="React Hook Form" dataIndex="hookForm" width={160} />
464 |       <Table.Column title="Formily1.x" dataIndex="formily1.x" width={160} />
465 |       <Table.Column title="Formily2.x" dataIndex="formily2.x" width={160} />
466 |     </Table>
467 |   )
468 | }
469 | ```
470 | 
471 | ## Core Advantages
472 | 
473 | - high performance
474 | - Out of the box
475 | - Linkage logic to achieve high efficiencyv
476 | - Cross-terminal capability, logic can be cross-frame, cross-terminal reuse
477 | - Dynamic rendering capability
478 | 
479 | ## Core Disadvantage
480 | 
481 | - The learning cost is relatively high. Although 2.x has already converged a large number of concepts, there is still a certain learning cost.
482 | 
483 | ## Who is using it?
484 | 
485 | - Alibaba
486 | - Tencent
487 | - ByteDance
488 | 
489 | ## Q/A
490 | 
491 | Q: Now that I have Vue, why do I still need to provide @formily/vue?
492 | 
493 | Answer: Vue is a UI framework. The problem it solves is a wider range of UI problems. Although its reactive ability is outstanding in form scenarios, at least it is more convenient than native React to write forms, but if it is in more complex form scenarios , We still need to do a lot of abstraction and encapsulation, so @formily/vue is to help you do these abstract encapsulation things, really let you develop super-complex form applications efficiently and conveniently.
494 | 
495 | Q: What is the biggest advantage of Formily2.x compared to 1.x?
496 | 
497 | Answer: The cost of learning, yes, the core is to allow users to understand Formily more quickly. We have tried our best to avoid all kinds of obscure logic and boundary problems during the 2.x design process.
498 | 
499 | Q: What is the browser compatibility of Formily 2.x?
500 | 
501 | Answer: IE is not supported, because the implementation of Reactive strongly relies on Proxy.
502 | 
```
Page 38/52FirstPrevNextLast