tmagic-editor/docs/api/form/submit-form.html
2026-09-07 12:28:47 +00:00

222 lines
102 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en-US" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>submitForm 函数 | tmagic-editor</title>
<meta name="description" content="页面可视化平台">
<meta name="generator" content="VitePress v2.0.0-alpha.19">
<link rel="preload stylesheet" href="/tmagic-editor/docs/assets/style.DMyGj5z2.css" as="style">
<link rel="preload stylesheet" href="/tmagic-editor/docs/vp-icons.css" as="style">
<script type="module" src="/tmagic-editor/docs/assets/chunks/metadata.5306ad6b.js"></script>
<script type="module" src="/tmagic-editor/docs/assets/app.CsM3uE9o.js"></script>
<link rel="preload" href="/tmagic-editor/docs/assets/inter-roman-latin.BOE8-mWI.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="modulepreload" href="/tmagic-editor/docs/assets/chunks/theme.D72v8eko.js">
<link rel="modulepreload" href="/tmagic-editor/docs/assets/chunks/framework.BTDV-FQ9.js">
<link rel="modulepreload" href="/tmagic-editor/docs/assets/api_form_submit-form.md.CYRSW-Dn.lean.js">
<meta name="theme-color" content="#646cff">
<script id="check-dark-mode">(()=>{let e=localStorage.getItem(`vitepress-theme-appearance`)||`auto`,t=window.matchMedia(`(prefers-color-scheme: dark)`).matches;(!e||e===`auto`?t:e===`dark`)&&document.documentElement.classList.add(`dark`)})();</script>
<script id="check-mac-os">document.documentElement.classList.toggle(`mac`,/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
</head>
<body>
<div id="app"><div class="Layout" data-v-60a4fda8><!--[--><!--]--><!--[--><span tabindex="-1" data-v-a371d961></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-a371d961>Skip to content</a><!--]--><!----><header class="VPNav" data-v-60a4fda8 data-v-43b0f54c><div class="VPNavBar has-sidebar top" data-v-43b0f54c data-v-776cbfea><div class="wrapper" data-v-776cbfea><div class="container" data-v-776cbfea><div class="title" data-v-776cbfea><div class="VPNavBarTitle has-sidebar" data-v-776cbfea data-v-4f71764b><a class="title" href="/tmagic-editor/docs/" data-v-4f71764b><!--[--><!--]--><!--[--><img class="VPImage logo" src="./favicon.png" alt data-v-852a0b98><!--]--><span data-v-4f71764b>tmagic-editor</span><!--[--><!--]--></a></div></div><div class="content" data-v-776cbfea><div class="content-body" data-v-776cbfea><!--[--><!--]--><div class="VPNavBarSearch search" data-v-776cbfea data-v-e56aaf6f><!--[--><button type="button" class="VPNavBarSearchButton" aria-label="Search" aria-keyshortcuts="/ control+k meta+k" data-v-e56aaf6f data-v-7a374445><span class="vpi-search" aria-hidden="true" data-v-7a374445></span><span class="text" data-v-7a374445>Search</span><span class="keys" aria-hidden="true" data-v-7a374445><kbd class="key-cmd" data-v-7a374445></kbd><kbd class="key-ctrl" data-v-7a374445>Ctrl</kbd><kbd data-v-7a374445>K</kbd></span></button><!----><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-776cbfea data-v-8a09b170><span id="main-nav-aria-label" class="visually-hidden" data-v-8a09b170> Main Navigation </span><ul class="list" data-v-8a09b170><!--[--><li data-v-8a09b170><a class="VPLink link VPNavBarMenuLink" href="/tmagic-editor/docs/guide/" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>文档</span><!--]--></a></li><li data-v-8a09b170><a class="VPLink link VPNavBarMenuLink active" href="/tmagic-editor/docs/api/editor/props.html" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>Editor API</span><!--]--></a></li><li data-v-8a09b170><a class="VPLink link VPNavBarMenuLink" href="/tmagic-editor/docs/runtime-api/core/app.html" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>Runtime API</span><!--]--></a></li><li data-v-8a09b170><a class="VPLink link VPNavBarMenuLink" href="/tmagic-editor/docs/form-config/fields/text.html" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>表单配置</span><!--]--></a></li><li data-v-8a09b170><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://github.com/Tencent/tmagic-editor/releases" target="_blank" rel="noreferrer" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>更新日志</span><!--]--></a></li><li data-v-8a09b170><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://tencent.github.io/tmagic-editor/playground/index.html" target="_blank" rel="noreferrer" tabindex="0" data-v-8a09b170 data-v-812af69a><!--[--><span data-v-812af69a>Playground</span><!--]--></a></li><!--]--></ul></nav><!----><div class="VPNavBarAppearance appearance" data-v-776cbfea data-v-74508d43><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-74508d43 data-v-99df29c8 data-v-f119851c><span class="check" data-v-f119851c><span class="icon" data-v-f119851c><!--[--><span class="vpi-sun sun" data-v-99df29c8></span><span class="vpi-moon moon" data-v-99df29c8></span><!--]--></span></span></button></div><ul class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-776cbfea data-v-7e2655ab data-v-59a498a9><!--[--><li class="item" data-v-59a498a9><a class="VPSocialLink no-icon" href="https://github.com/Tencent/tmagic-editor" aria-label="github" target="_blank" rel="me noopener" data-v-59a498a9 data-v-00fbddfa><span class="vpi-social-github"></span></a></li><!--]--></ul><div class="VPFlyout VPNavBarExtra extra" data-v-776cbfea data-v-402401c4 data-v-94c5eb2e><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-94c5eb2e><span class="vpi-more-horizontal icon" data-v-94c5eb2e></span></button><div class="menu" data-v-94c5eb2e><div class="VPMenu" data-v-94c5eb2e data-v-8778dd73><!----><!--[--><!--[--><!----><div class="group" data-v-402401c4><div class="item appearance" data-v-402401c4><p class="label" data-v-402401c4>Appearance</p><div class="appearance-action" data-v-402401c4><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-402401c4 data-v-99df29c8 data-v-f119851c><span class="check" data-v-f119851c><span class="icon" data-v-f119851c><!--[--><span class="vpi-sun sun" data-v-99df29c8></span><span class="vpi-moon moon" data-v-99df29c8></span><!--]--></span></span></button></div></div></div><div class="group" data-v-402401c4><div class="item social-links" data-v-402401c4><ul class="VPSocialLinks social-links-list" data-v-402401c4 data-v-59a498a9><!--[--><li class="item" data-v-59a498a9><a class="VPSocialLink no-icon" href="https://github.com/Tencent/tmagic-editor" aria-label="github" target="_blank" rel="me noopener" data-v-59a498a9 data-v-00fbddfa><span class="vpi-social-github"></span></a></li><!--]--></ul></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-776cbfea data-v-f3a533b5><span class="container" data-v-f3a533b5><span class="top" data-v-f3a533b5></span><span class="middle" data-v-f3a533b5></span><span class="bottom" data-v-f3a533b5></span></span></button></div></div></div></div><div class="divider" data-v-776cbfea><div class="divider-line" data-v-776cbfea></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-60a4fda8 data-v-3c5edcbb><div class="container" data-v-3c5edcbb><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-3c5edcbb><span class="vpi-align-left menu-icon" data-v-3c5edcbb></span><span class="menu-text" data-v-3c5edcbb>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-allow-mismatch="style" data-v-3c5edcbb data-v-f3e9b1b1><button data-v-f3e9b1b1>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-60a4fda8 data-v-befba6b7><div class="curtain" data-v-befba6b7></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-befba6b7><span class="visually-hidden" id="sidebar-aria-label" data-v-befba6b7> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-a3c028c0><section class="VPSidebarItem level-0" data-v-a3c028c0 data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h2 class="text" data-v-b2cd6471>编辑器</h2><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>Editor组件</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/props.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>props</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/slots.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>slots</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/events.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>events</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>editorService</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/editorServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>方法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/editorServiceEvents.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>事件</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>propsService</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/propsServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>方法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/propsServiceEvents.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>事件</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>historyService</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/historyServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>方法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/historyServiceEvents.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>事件</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><div class="VPSidebarItem level-1 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/eventsServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>eventsService</p><!--]--></a><!----></div><!----></div><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>uiService</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/uiServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>方法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/uiServiceEvents.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>事件</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><div class="VPSidebarItem level-1 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/codeBlockServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>codeBlockService</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/componentListServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>componentListService</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/editor/storageServiceMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>storageService</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section></div><div class="no-transition group" data-v-a3c028c0><section class="VPSidebarItem level-0" data-v-a3c028c0 data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h2 class="text" data-v-b2cd6471>表单</h2><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>Form组件</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-props.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>props</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-methods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>methods</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-events.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>events</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>FormDialog组件</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-dialog-props.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>props</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-dialog-methods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>methods</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/form-dialog-events.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>events</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>工具函数</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/form/submit-form.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>submitForm</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><!--]--></li></ul></section></div><div class="no-transition group" data-v-a3c028c0><section class="VPSidebarItem level-0" data-v-a3c028c0 data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h2 class="text" data-v-b2cd6471>表格</h2><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>Table组件</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/table/props.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>props</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/table/methods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>methods</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/table/events.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>events</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><!--]--></li></ul></section></div><div class="no-transition group" data-v-a3c028c0><section class="VPSidebarItem level-0" data-v-a3c028c0 data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h2 class="text" data-v-b2cd6471>stage</h2><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><section class="VPSidebarItem level-1" data-v-b2cd6471><div class="item" role="button" tabindex="0" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><h3 class="text" data-v-b2cd6471>StageCore</h3><!----></div><ul class="items" data-v-b2cd6471><li data-v-b2cd6471><!--[--><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/stage/coreMethods.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>方法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-b2cd6471><div class="item" data-v-b2cd6471><div class="indicator" data-v-b2cd6471></div><a class="VPLink link link" href="/tmagic-editor/docs/api/stage/coreEvents.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>事件</p><!--]--></a><!----></div><!----></div><!--]--></li></ul></section><!--]--></li></ul></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-60a4fda8 data-v-5cafe042><div class="VPDoc has-sidebar has-aside" data-v-5cafe042 data-v-ecefb870><!--[--><!--]--><div class="container" data-v-ecefb870><div class="aside" data-v-ecefb870><div class="aside-curtain" data-v-ecefb870></div><div class="aside-container" data-v-ecefb870><div class="aside-content" data-v-ecefb870><div class="VPDocAside" data-v-ecefb870 data-v-ccaf1b72><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-ccaf1b72 data-v-2b1043b8><div class="content" data-v-2b1043b8><div class="outline-marker" data-v-2b1043b8></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-2b1043b8>On this page</div><ul class="VPDocOutlineItem root" data-v-2b1043b8 data-v-1b6389b6><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-ccaf1b72></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-ecefb870><div class="content-container" data-v-ecefb870><!--[--><!--]--><main class="main" data-v-ecefb870><div style="position:relative;" class="vp-doc _tmagic-editor_docs_api_form_submit-form" data-v-ecefb870><div><h1 id="submitform-函数" tabindex="-1">submitForm 函数 <a class="header-anchor" href="#submitform-函数" aria-label="Permalink to “submitForm 函数”"></a></h1><p>以命令式方式对一份「表单配置 + 表单值」执行一次校验并取回表单值,类似 <code>ElMessage</code> 的用法。</p><p><strong>无渲染</strong>实现:不创建任何 DOM 容器、不实例化任何组件,而是直接遍历 <code>config</code> 树收集带规则的字段,交给 <a href="https://github.com/yiminghe/async-validator" target="_blank" rel="noreferrer"><code>async-validator</code></a><code>element-plus</code> 内部用的也是它)执行。因此它可以在 Node / CI 等没有 DOM 的环境中使用,也省去了挂载整棵表单的开销。校验通过则 <code>resolve</code> 表单值,失败则 <code>reject</code> 错误信息。纯 Node 请从 <code>@tmagic/form/headless</code> 引入,避免加载 Vue 组件和样式。</p><p>适用于一些没有合适的容器、但又需要复用 <code>MForm</code> 校验逻辑的场景,例如:</p><ul><li>通过快捷菜单/命令面板触发一次性表单</li><li>在脚本/服务层完成一次表单值校验后再发请求</li><li><code>config</code> 配置当作&quot;可执行的校验规则&quot;使用</li><li>在 Node 脚本 / CI 中批量校验组件配置</li></ul><h2 id="无渲染校验与自定义字段登记" tabindex="-1">无渲染校验与自定义字段登记 <a class="header-anchor" href="#无渲染校验与自定义字段登记" aria-label="Permalink to “无渲染校验与自定义字段登记”"></a></h2><p>无渲染实现按 <code>Container.vue</code> 及各容器组件的模板规则遍历配置树,产出的字段 <code>prop</code> 与规则与「挂载 <code>MForm</code> 后调用 <code>validate()</code>」等价。需要 UI 时传入 <code>dialog: true</code>,会把表单以弹层渲染出来供填写/确认。</p><p>字段只要带了 <code>rules</code>(会包 FormItem就会校验自身不必先登记为叶子。配置里有 <code>items</code> 会下钻子项。内部再渲染 <code>MContainer</code> 的复合字段需要 <code>registerField(type, { innerConfig })</code>把内部会挂到父表单上的配置交出来。innerConfig 回调自身抛错时,会以 <code>FieldInnerConfigError</code><code>code: &#39;FIELD_INNER_CONFIG&#39;</code>reject。</p><p>innerConfig 回调在校验和表单值初始化两条链路上都会被调用(后者用于走到复合字段内部、找出需要执行 <code>effect</code> 的子字段),所以它应当只做配置派生、可重复调用、不要做重活。在表单值初始化链路上,回调抛错只会记录到 console 并跳过该子树,不会让表单渲染不出来。</p><p>自定义字段的渲染组件和无渲染校验都通过 <code>registerField</code> / <code>registerFields</code> 一次登记。<code>component</code> 会写入字段注册表(<code>getFormField</code>);传入 <code>app</code> 时同时 <code>app.component(&#39;m-fields-*&#39;)</code>。容器组件用 <code>container</code>,对应 <code>m-form-*</code></p><p>字段对表单值的初始化写入统一登记为 <code>effect</code>,渲染与无渲染共用同一份登记表,执行点也只有一个:表单值初始化完成后(<code>MForm</code> 内部、<code>validateValues</code>、以及 tab / table 新增行时)各执行一次 <code>applyMountValueEffects</code>,字段组件自身不要在 <code>setup</code> 里改写 <code>model</code>。因此 effect 有两个约束:一是必须幂等,同一份值可能被执行多次(如 <code>initValues</code> 变化后重新初始化);二是不看 <code>display</code><code>display: false</code> 或函数返回假的字段也会被规整,避免字段由隐藏转为显示时漏掉)。<code>type: &#39;hidden&#39;</code> 不同:遍历在该节点停止、不往下分派,内部字段不会执行 effect。需要按路径跨层级写值时用上下文里的 <code>values</code>(本次处理的值根对象,<code>prop</code> 即以它为根),不要用 <code>mForm.values</code>——对比模式处理的是 <code>lastValues</code> 那一份,新增行处理的则是还没挂到表单上的一行值。单个 effect 抛错只会记录到 console不影响其余字段与表单渲染。复合字段可以同时登记 <code>effect</code><code>innerConfig</code>:前者改本字段的值,后者只派生内部配置、不要在回调里改 <code>model</code></p><table tabindex="0"><thead><tr><th>字段形态</th><th>登记方式</th></tr></thead><tbody><tr><td>自身带 <code>rules</code>,内部没有嵌套的父表单 FormItem</td><td>无需登记,直接校验</td></tr><tr><td>内部只渲染叶子 UI或把子表单渲染在独立的 <code>MForm</code> / <code>MFormBox</code> 实例里</td><td><code>registerField(&#39;my-field&#39;)</code>(配置里有 <code>items</code> 但不属于父表单时,避免被当下钻)</td></tr><tr><td>同时需要渲染组件</td><td><code>registerField(&#39;my-field&#39;, { component })</code></td></tr><tr><td>容器组件(<code>m-form-*</code></td><td><code>registerField(&#39;my-box&#39;, { container, walk })</code></td></tr><tr><td>叶子字段,但需要改写表单值(类似 <code>display</code><code>initValue</code></td><td><code>registerField(&#39;my-field&#39;, { effect })</code></td></tr><tr><td>内部再渲染 <code>MContainer</code> / <code>MPanel</code> / <code>MGroupList</code>,向父表单注册字段</td><td><code>registerField(&#39;my-field&#39;, { innerConfig })</code>(需要改本字段的值时再加 <code>effect</code></td></tr><tr><td>自定义 <code>typeMatch</code> 类型校验</td><td><code>registerField(&#39;my-field&#39;, { typeMatch })</code></td></tr></tbody></table><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { registerField, registerFields } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> MyColorPicker </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;./MyColorPicker.vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// 叶子字段:内部没有嵌套的表单项;带 component 时即可渲染</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerFields</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-color-picker&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { component: MyColorPicker } });</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// 需要挂到当前 app 时传入第二个参数</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerFields</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-color-picker&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { component: MyColorPicker } }, app);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// 叶子字段,但需要改写表单值:写成 effect不要在组件 setup 里改 model</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-status&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> effect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: ({ </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">model</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ((config </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">as</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).initValue </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model[(config </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">as</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).name] </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (config </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">as</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">).initValue;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// 复合字段:把组件内部渲染的 MContainer 配置交出来</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> innerConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: ({ </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">model</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">prop</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> // 对应组件内部 &lt;MContainer :config=&quot;childConfig&quot; :model=&quot;model[name]&quot; :prop=&quot;prop&quot;&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: childConfig,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model: model[config.name],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prop,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// typeMatch覆盖或扩展该 type 的类型匹配校验,可与 innerConfig / effect 同时登记</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-status&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> typeMatch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">value</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">message</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> value </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;string&#39;</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> undefined</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> :</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;应为字符串&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>返回的 <code>config</code><code>name</code> 会被追加到返回的 <code>prop</code> 上。因此当内部配置复用了字段自身的 <code>name</code>(例如内部渲染 <code>&lt;MGroupList :config=&quot;{ name, items }&quot; :model=&quot;model&quot; :prop=&quot;prop&quot;&gt;</code>)时,要返回 <code>parentProp</code> 而非 <code>prop</code>,否则 <code>name</code> 会被拼两次:</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-list&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> innerConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: ({ </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">parentProp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: { type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;group-list&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: config.name, items: innerItems },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prop: parentProp,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>编辑器侧四个复合字段(<code>code-select</code> / <code>display-conds</code> / <code>event-select</code> / <code>style-setter</code>)的登记可参考 <code>packages/editor/src/fields/headless-validation.ts</code>innerConfig 与组件共用同一份配置工厂(<code>packages/editor/src/fields/configs/</code>),避免两条链路各写一份而逐渐跑偏。</p><p><code>type: &#39;component&#39;</code> 会把 <code>config.component</code> 当任意 Vue 组件渲染。无渲染校验把它视为叶子,<strong>不会</strong>遍历内部结构。因此该组件不得再向父表单注册 FormItem需要嵌套表单项时应对该具体组件 <code>registerField(type, { innerConfig })</code></p><h3 id="重复登记与撤销" tabindex="-1">重复登记与撤销 <a class="header-anchor" href="#重复登记与撤销" aria-label="Permalink to “重复登记与撤销”"></a></h3><p>同一个 type 多次登记按字段浅合并,后一次只覆盖自己传入的 key</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { innerConfig });</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { component: MyComposite }); </span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// innerConfig 仍在</span></span></code></pre></div><p>登记分「内置」与「业务」两层。<code>app.use(MagicForm)</code> / <code>registerBuiltInFields</code> 写内置层,<code>registerField</code> / <code>registerFields</code> 写业务层;读取时业务层优先,<code>unregisterField</code> / <code>clearFields</code> 只清业务层,内置字段不受影响(单测里 <code>clearFields</code> 之后仍能校验 <code>text</code><code>tab</code> 等内置 type</p><p>因为是合并语义,把一个已登记 <code>innerConfig</code> 的 type 改成普通叶子,不能靠再传一次空对象,要先撤销:</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {}); </span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// ✗ 合并后 innerConfig 还在,仍会下钻</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">unregisterField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">); </span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// ✓ 先清掉业务层登记</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerField</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;my-composite&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { component: MyComposite });</span></span></code></pre></div><p>一次登记里同时传多个形态时的优先级:<code>walk</code> &gt; <code>innerConfig</code> &gt; <code>effect</code>(叶子),命中低优先级的那份会被忽略并在控制台给出告警。</p><h2 id="签名" tabindex="-1">签名 <a class="header-anchor" href="#签名" aria-label="Permalink to “签名”"></a></h2><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">options</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SubmitFormOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;;</span></span></code></pre></div><h2 id="参数" tabindex="-1">参数 <a class="header-anchor" href="#参数" aria-label="Permalink to “参数”"></a></h2><p><code>options</code><code>MForm</code> 组件的 props 基本对齐,额外提供了 <code>native</code><code>returnChangeRecords</code><code>dialog</code><code>signal</code> 等参数。<code>appContext</code><code>dialog: true</code> 时生效。</p><table tabindex="0"><thead><tr><th>名称</th><th>类型</th><th>默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>config</code></td><td><code>FormConfig</code></td><td></td><td>必填,表单配置</td></tr><tr><td><code>initValues</code></td><td><code>Record&lt;string, any&gt;</code></td><td><code>{}</code></td><td>表单初始值</td></tr><tr><td><code>lastValues</code></td><td><code>Record&lt;string, any&gt;</code></td><td><code>{}</code></td><td>需对比的值(开启对比模式时传入)</td></tr><tr><td><code>isCompare</code></td><td><code>boolean</code></td><td><code>false</code></td><td>是否开启对比模式</td></tr><tr><td><code>parentValues</code></td><td><code>Record&lt;string, any&gt;</code></td><td><code>{}</code></td><td>父级 values透传给字段的回调</td></tr><tr><td><code>labelWidth</code></td><td><code>string</code></td><td><code>&#39;200px&#39;</code></td><td>label 宽度</td></tr><tr><td><code>disabled</code></td><td><code>boolean</code></td><td><code>false</code></td><td>是否禁用</td></tr><tr><td><code>height</code></td><td><code>string</code></td><td><code>&#39;auto&#39;</code></td><td>表单高度</td></tr><tr><td><code>stepActive</code></td><td><code>string | number</code></td><td><code>1</code></td><td>步骤表单当前激活步骤</td></tr><tr><td><code>size</code></td><td><code>&#39;small&#39; | &#39;default&#39; | &#39;large&#39;</code></td><td></td><td>组件尺寸</td></tr><tr><td><code>inline</code></td><td><code>boolean</code></td><td><code>false</code></td><td>是否行内表单</td></tr><tr><td><code>labelPosition</code></td><td><code>string</code></td><td><code>&#39;right&#39;</code></td><td>label 对齐方式</td></tr><tr><td><code>keyProp</code></td><td><code>string</code></td><td><code>&#39;__key&#39;</code></td><td>配置项的唯一 key</td></tr><tr><td><code>popperClass</code></td><td><code>string</code></td><td></td><td>弹层 className</td></tr><tr><td><code>preventSubmitDefault</code></td><td><code>boolean</code></td><td></td><td>是否阻止表单原生 submit</td></tr><tr><td><code>useFieldTextInError</code></td><td><code>boolean</code></td><td><code>true</code></td><td>校验失败时错误提示前缀是否使用字段的 <code>text</code> 文案;<code>false</code> 时直接使用字段 <code>name</code></td></tr><tr><td><code>context</code></td><td><code>FormContext</code></td><td></td><td>宿主业务上下文,与 MForm 的 <code>context</code> 语义一致;配置回调通过 <code>mForm.xxx</code> 读穿取用</td></tr><tr><td><code>native</code></td><td><code>boolean</code></td><td><code>false</code></td><td>透传给 <code>Form.submitForm</code><code>true</code> 时返回内部响应式 <code>values</code>,否则返回 <code>cloneDeep(toRaw(values))</code></td></tr><tr><td><code>returnChangeRecords</code></td><td><code>boolean</code></td><td><code>false</code></td><td><code>true</code> 时 resolve 结果为 <code>{ values, changeRecords }</code>,携带表单变更记录;否则仅 resolve <code>values</code></td></tr><tr><td><code>appContext</code></td><td><code>AppContext | null</code></td><td><code>null</code></td><td>父级 Vue 应用上下文。仅 <code>dialog: true</code> 时生效用于继承全局组件、指令、provide 等,常通过 <code>app._context</code><code>getCurrentInstance()?.appContext</code> 获取</td></tr><tr><td><code>dialog</code></td><td><code>boolean</code></td><td><code>false</code></td><td><code>true</code> 时把表单以弹层形式渲染出来,点击「确定」才提交,「取消」则以 reject 中断;校验失败会保留弹层并展示错误,便于修正后重试。等待人工操作,可用 <code>signal</code> 中断</td></tr><tr><td><code>title</code></td><td><code>string</code></td><td><code>&#39;submitForm&#39;</code> / <code>&#39;validateForm&#39;</code></td><td>弹层标题,仅 <code>dialog: true</code> 时生效</td></tr><tr><td><code>signal</code></td><td><code>AbortSignal</code></td><td></td><td>外部中断信号。abort 时立即以 <code>signal.reason</code> reject并卸载 <code>dialog</code> 模式下已挂载的临时表单实例</td></tr></tbody></table><h2 id="返回值" tabindex="-1">返回值 <a class="header-anchor" href="#返回值" aria-label="Permalink to “返回值”"></a></h2><ul><li><code>校验通过</code><code>Promise&lt;any&gt;</code> resolve 当前表单值(<code>native</code> 决定是否克隆);当 <code>returnChangeRecords</code><code>true</code>resolve <code>{ values, changeRecords }</code></li><li><code>校验失败</code><code>Promise&lt;any&gt;</code> reject 一个 <code>Error</code><code>message</code> 中包含逐条字段错误信息(格式 <code>${text} -&gt; ${message}</code>,多条用 <code>&lt;br&gt;</code> 分隔)</li></ul><p><code>dialog: true</code> 时无论成功或失败,函数都会在最后自动 <code>unmount</code> 内部 app 并移除挂载用的 DOM 容器,无需调用方手动清理。</p><div class="tip custom-block"><p class="custom-block-title">关于 changeRecords</p><p><code>changeRecords</code> 记录的是表单挂载后发生的字段变更(由各字段的 <code>change</code> 事件累积而来)。无渲染校验没有用户交互,因此固定返回空数组;只有 <code>dialog: true</code> 时才可能有内容(<code>MForm</code> 内部的 <code>submitForm</code> 在校验通过后会清空变更记录,因此本函数会在调用前先做快照)。</p></div><h2 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to “基础用法”"></a></h2><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { submitForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> values</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;username&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rules: [</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { required: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;请输入用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { typeMatch: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;用户名类型不合法&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initValues: { username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;提交成功&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, values);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">} </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (e) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;校验失败&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, e);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="同时获取变更记录-changerecords" tabindex="-1">同时获取变更记录changeRecords <a class="header-anchor" href="#同时获取变更记录-changerecords" aria-label="Permalink to “同时获取变更记录changeRecords”"></a></h2><p>设置 <code>returnChangeRecords: true</code>resolve 的结果会从单纯的 <code>values</code> 变为 <code>{ values, changeRecords }</code></p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { submitForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">values</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">changeRecords</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: [{ type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;username&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initValues: { username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;foo&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> returnChangeRecords: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(values); </span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// { username: &#39;foo&#39; }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(changeRecords); </span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// ChangeRecord[]</span></span></code></pre></div><h2 id="弹层模式-dialog-true-下继承父级应用上下文" tabindex="-1">弹层模式(<code>dialog: true</code>)下继承父级应用上下文 <a class="header-anchor" href="#弹层模式-dialog-true-下继承父级应用上下文" aria-label="Permalink to “弹层模式dialog: true下继承父级应用上下文”"></a></h2><p>默认路径不挂载组件,不需要 <code>appContext</code>。只有 <code>dialog: true</code> 会渲染弹层,此时 <code>MForm</code> 要用到 <code>@tmagic/design</code> 的组件(背后可能是 <code>element-plus</code><code>tdesign</code>),需要把宿主应用的上下文带过去:</p><div class="language-vue"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">vue</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setup</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;ts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { getCurrentInstance } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { submitForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">appContext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getCurrentInstance</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onClick</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> values</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: [{ type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;文本&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initValues: { text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;hello&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> dialog: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> title: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;编辑配置&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> appContext,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(values);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;/</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span></code></pre></div><p>也可以在初始化 app 时把上下文缓存下来,再在任意位置复用:</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createApp } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ElementPlus </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;element-plus&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> MagicForm, { </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> SubmitFormOptions, submitForm </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">as</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rawSubmitForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> App </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;./App.vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> app</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createApp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(App);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ElementPlus);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(MagicForm);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mount</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;#app&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">options</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Omit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">SubmitFormOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;appContext&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=&gt;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> rawSubmitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">...</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">options, appContext: app._context });</span></span></code></pre></div><h2 id="处理校验错误" tabindex="-1">处理校验错误 <a class="header-anchor" href="#处理校验错误" aria-label="Permalink to “处理校验错误”"></a></h2><p>校验失败时 reject 的 <code>Error.message</code> 已经把出错字段拼好,可以直接展示到用户:</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { tMagicMessage } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/design&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">try</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> values</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ config, initValues });</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> save</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(values);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">} </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">catch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tMagicMessage.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> dangerouslyUseHTMLString: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: e.message,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="validateform-函数" tabindex="-1">validateForm 函数 <a class="header-anchor" href="#validateform-函数" aria-label="Permalink to “validateForm 函数”"></a></h2><p><code>validateForm</code><code>submitForm</code> 共用同一套无渲染校验实现,区别在于它是<strong>静默</strong>的:校验失败不抛异常、不返回表单值,而是以返回值形式给出错误文案。适合「只想探测这份配置是否合法」的场景,例如源码编辑器保存后校验、批量校验组件配置。</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validateForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">options</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ValidateFormOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;;</span></span></code></pre></div><p><code>options</code><code>SubmitFormOptions</code> 中与校验相关的子集(<code>config</code><code>initValues</code><code>parentValues</code><code>labelWidth</code><code>keyProp</code><code>useFieldTextInError</code><code>extendState</code><code>typeMatchValid</code><code>appContext</code><code>dialog</code><code>title</code><code>signal</code>)。</p><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { validateForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validateForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: [{ type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;username&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, rules: [{ required: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;请输入用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }] }],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initValues: { username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> // &#39;用户名 -&gt; 请输入用户名&#39;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>校验通过返回空字符串 <code>&#39;&#39;</code>,否则返回以 <code>&lt;br&gt;</code> 拼接的错误文案。无法完成校验时才会 reject例如 innerConfig 回调失败抛出 <code>FieldInnerConfigError</code>)。</p><h2 id="运行环境" tabindex="-1">运行环境 <a class="header-anchor" href="#运行环境" aria-label="Permalink to “运行环境”"></a></h2><p>无渲染实现不接触 <code>document</code> / <code>window</code>,因此在任何 JS 运行时中都可用:</p><table tabindex="0"><thead><tr><th>环境</th><th>是否可用</th><th>说明</th></tr></thead><tbody><tr><td>浏览器 / Electron 渲染进程 / 浏览器扩展</td><td></td><td>直接可用</td></tr><tr><td>Vitest / Jest + <code>happy-dom</code> / <code>jsdom</code></td><td></td><td>项目自身的单测就跑在这种环境下</td></tr><tr><td>纯 Node.js / Bun / Deno无 DOM polyfill</td><td></td><td><code>@tmagic/form/headless</code> 引入,不要用 <code>@tmagic/form</code> 主入口</td></tr></tbody></table><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// scripts/check-form.ts —— 纯 Node 环境,无需任何 DOM polyfill</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { builtInFields, registerBuiltInFields, registerFields, validateForm } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/form/headless&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { editorFields } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@tmagic/editor/headless&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">// `builtInFields` 只是数据;未 `app.use(MagicForm)` 时要自己登记</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerBuiltInFields</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(builtInFields);</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerFields</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(editorFields);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> error</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> validateForm</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: [{ type: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;text&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;username&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, text: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;用户名&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, rules: [{ required: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }] }],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> initValues: { username: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (error) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">error</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(error);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> process.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">exit</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><div class="warning custom-block"><p class="custom-block-title">注意</p><p><code>dialog: true</code> 依赖 DOM 与已安装的 UI 库(<code>element-plus</code> / <code>tdesign</code>),在纯 Node 环境中不可用。</p></div><div class="warning custom-block"><p class="custom-block-title">ESM 与 CJS 不要混用</p><p><code>@tmagic/form/headless</code> 的 ESM 产物与 <code>@tmagic/form</code> 共用同一批模块文件,字段注册表是同一份,两个入口可以混着 <code>import</code></p><p>CJS 产物是两个各自独立的 bundle注册表不共享。所以同一进程里不要同时 <code>require(&#39;@tmagic/form&#39;)</code><code>require(&#39;@tmagic/form/headless&#39;)</code>——在一边 <code>registerField</code> 另一边读不到,校验会因为「没登记过这个 type」而静默放过。<code>@tmagic/editor</code><code>@tmagic/design</code> 的 headless 子路径同理。</p></div><h2 id="类型定义" tabindex="-1">类型定义 <a class="header-anchor" href="#类型定义" aria-label="Permalink to “类型定义”"></a></h2><details class="details custom-block"><summary>查看 <code>SubmitFormOptions</code> 类型定义</summary><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">/**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * submitForm 函数参数(与 Form.vue 组件 props 对齐)</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SubmitFormOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 表单配置 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> config</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> FormConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 表单初始值 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> initValues</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 需对比的值(开启对比模式时传入) */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> lastValues</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 是否开启对比模式 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> isCompare</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> parentValues</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> labelWidth</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> disabled</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> height</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> stepActive</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> number</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> size</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;small&#39;</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;default&#39;</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;large&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> inline</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> labelPosition</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;top&#39;</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;left&#39;</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;right&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> keyProp</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> popperClass</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> preventSubmitDefault</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 表单校验失败时,错误提示前缀是否使用字段的 text 文案(通过 `getTextByName` 从 config 中查找)。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 默认 `true`,置为 `false` 时直接使用字段 name。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> useFieldTextInError</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 宿主业务上下文,与 MForm 的同名 prop 语义一致 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> context</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> FormContext</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 透传给 Form.submitForm 的参数:是否直接返回原始响应式 values */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> native</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 是否在 resolve 结果中携带 changeRecords变更记录</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 开启后 resolve 的结果为 `{ values, changeRecords }`,否则仅 resolve values。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> returnChangeRecords</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 父级应用上下文用于继承全局组件、指令、provide 等。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 仅 `dialog: true` 时生效。`@tmagic/form/headless` 不支持弹层。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> appContext</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AppContext</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 是否以弹层展示表单。默认 `false`。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> *</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * `@tmagic/form/headless` 不支持 `dialog: true`,请从 `@tmagic/form` 引入。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> dialog</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 弹层标题,仅 `dialog: true` 时生效。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> title</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> typeMatchValid</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 外部中断信号。abort 时会立即以 `signal.reason` reject。</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> signal</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbortSignal</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div></details><details class="details custom-block"><summary>查看 <code>SubmitFormResult</code> 类型定义</summary><div class="language-ts"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;">/**</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> * 开启 `returnChangeRecords` 时 submitForm 的返回结果</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> */</span></span>
<span class="line"><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SubmitFormResult</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 校验通过后的表单值 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> values</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> /** 表单变更记录 */</span></span>
<span class="line"><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;"> changeRecords</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ChangeRecord</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">[];</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div></details></div></div></main><footer class="VPDocFooter" data-v-ecefb870 data-v-283d6eff><!--[--><!--]--><!----><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-283d6eff><span class="visually-hidden" id="doc-footer-aria-label" data-v-283d6eff>Pager</span><div class="pager" data-v-283d6eff><a class="VPLink link pager-link prev" href="/tmagic-editor/docs/api/form/form-dialog-events.html" data-v-283d6eff><!--[--><span class="desc" data-v-283d6eff>Previous page</span><span class="title" data-v-283d6eff>events</span><!--]--></a></div><div class="pager" data-v-283d6eff><a class="VPLink link pager-link next" href="/tmagic-editor/docs/api/table/props.html" data-v-283d6eff><!--[--><span class="desc" data-v-283d6eff>Next page</span><span class="title" data-v-283d6eff>props</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-60a4fda8 data-v-5376ca3c><div class="container" data-v-5376ca3c><p class="message" data-v-5376ca3c>Powered by 腾讯视频会员平台技术中心</p><p class="copyright" data-v-5376ca3c>Copyright (C) 2025 Tencent.</p></div></footer><!--[--><!--]--></div></div>
</body>
</html>