mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-09-11 02:55:47 +08:00
207 lines
84 KiB
HTML
207 lines
84 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US" dir="ltr">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>RUNTIME | 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/guide_runtime.md.jikJ4KMO.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 active" 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" 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><!--[--><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/guide/introduction.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>介绍</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/guide/" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>快速开始</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/guide/runtime.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>RUNTIME</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/guide/component.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>组件开发</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/guide/conception.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>基础概念</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/guide/publish.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>页面发布</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/guide/editor-expand.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>编辑器扩展</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/guide/migration.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>升级到1.5.x</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><!--[--><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/guide/advanced/js-schema.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>JS Schema</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/guide/advanced/layout.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>布局原理</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/guide/advanced/page.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>页面渲染</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/guide/advanced/coupling.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>联动原理</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/guide/advanced/code-block.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>代码块</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/guide/advanced/data-source.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>数据源</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/guide/advanced/history-list.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>历史记录面板</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/guide/advanced/tmagic-form.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>@tmagic/form</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/guide/advanced/prop-form-validate.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>属性配置表单校验联动</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><!--[--><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/guide/tutorial/" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>写在前面</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/guide/tutorial/hello-world.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>1.Hello World</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/guide/tutorial/runtime.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>2.Runtime</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/guide/tutorial/render.html" data-v-b2cd6471><!--[--><p class="text" data-v-b2cd6471>3.DSL解析渲染</p><!--]--></a><!----></div><!----></div><!--]--></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_guide_runtime" data-v-ecefb870><div><h1 id="runtime" tabindex="-1">RUNTIME <a class="header-anchor" href="#runtime" aria-label="Permalink to “RUNTIME”"></a></h1><p>本章详细介绍 tmagic-editor 中 runtime 的概念、目录结构与实现方式。所有内容均与开源仓库 <a href="https://github.com/Tencent/tmagic-editor/tree/master/runtime/vue" target="_blank" rel="noreferrer"><code>runtime/vue/</code></a> 一一对应,可以对照阅读。</p><h2 id="runtime-是什么" tabindex="-1">runtime 是什么 <a class="header-anchor" href="#runtime-是什么" aria-label="Permalink to “runtime 是什么”"></a></h2><p><strong>runtime 是用来解析 DSL 的执行环境</strong>。编辑器只负责生成 DSL,最终把它<strong>渲染成可见页面</strong>的工作交给 runtime。</p><p>在一份完整的 tmagic-editor 项目中,runtime 同时承担两个角色:</p><table tabindex="0"><thead><tr><th>角色</th><th>入口</th><th>用途</th></tr></thead><tbody><tr><td><strong>page</strong></td><td><code>runtime/vue/page/</code></td><td>线上发布产物,加载 <code>window.magicDSL</code> 渲染真实页面</td></tr><tr><td><strong>playground</strong></td><td><code>runtime/vue/playground/</code></td><td>编辑器中央 iframe 加载的画布,响应增删改并渲染所见即所得</td></tr></tbody></table><p>两者共用同一份组件、插件、数据源代码,只在入口(<code>main.ts</code> / <code>App.vue</code>)上有差异。</p><div class="tip custom-block"><p class="custom-block-title custom-block-title-default">TIP</p><p>DSL、playground 与 editor 之间的通信原理可以前往<a href="/tmagic-editor/docs/guide/tutorial/">教程</a>继续了解。</p></div><h2 id="创建-runtime-项目" tabindex="-1">创建 runtime 项目 <a class="header-anchor" href="#创建-runtime-项目" aria-label="Permalink to “创建 runtime 项目”"></a></h2><div class="tip custom-block"><p class="custom-block-title custom-block-title-default">TIP</p><p>推荐用 <code>npm create tmagic@latest</code> / <code>pnpm create tmagic</code> 快速生成 runtime 模板,按提示选择 <code>runtime</code> 即可。</p></div><p>生成的项目结构如下(与 <a href="https://github.com/Tencent/tmagic-editor/tree/master/runtime/vue" target="_blank" rel="noreferrer"><code>runtime/vue/</code></a> 完全一致):</p><div class="language-bash"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">bash</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;">runtime/vue</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> page/</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 线上 page 入口</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> App.vue</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> index.html</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> main.ts</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> └──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> utils/</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> playground/</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 编辑器内 iframe 入口</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> App.vue</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> index.html</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">│</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> └──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> main.ts</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> public/</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> scripts/</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # build 脚本(res / page / playground / all)</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> tmagic.config.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # @tmagic/cli 配置:声明组件、插件、数据源</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> tmagic.config.local.ts#</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 本地覆盖配置(可选)</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">└──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vite.config.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 多入口构建:page + playground</span></span></code></pre></div><h2 id="tmagic-config-ts-声明组件-插件-数据源" tabindex="-1">tmagic.config.ts:声明组件 / 插件 / 数据源 <a class="header-anchor" href="#tmagic-config-ts-声明组件-插件-数据源" aria-label="Permalink to “tmagic.config.ts:声明组件 / 插件 / 数据源”"></a></h2><p><code>tmagic.config.ts</code> 是 <a href="./publish.html#tmagic-cli">@tmagic/cli</a> 的入口,它会扫描 <code>packages</code> 列表,生成 <code>.tmagic/comp-entry.ts</code> 等 5 个入口文件,runtime 只需要从这些入口里 <code>import</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;"> { defineConfig } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/cli'</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;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> componentFileAffix: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'.vue'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> // 是否使用 vite + 异步组件,详见 page/main.ts 中的 defineAsyncComponent</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> dynamicImport: </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;"> npmConfig: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> client: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'pnpm'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> keepPackageJsonClean: </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 style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> packages: [</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> // key 为组件 type,需要与编辑器中 componentGroupList 的 type 对应</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> button: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-button'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> container: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-container'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> img: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-img'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'iterator-container'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-iterator-container'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> overlay: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-overlay'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> page: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-page'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'page-fragment'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-page-fragment'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'page-fragment-container'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-page-fragment-container'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> qrcode: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'@tmagic/vue-qrcode'</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;">'@tmagic/vue-text'</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></code></pre></div><p><code>tmagic.config.local.ts</code> 用于本地覆盖(不会被提交),常见用法是把线上 npm 包临时替换为本地组件目录调试。</p><p>执行 <code>npm run tmagic</code>(即 <code>tmagic entry</code>)后,runtime 根目录下会生成:</p><div class="language-bash"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">bash</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;">.tmagic/</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> comp-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # page 同步组件入口</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> async-comp-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # page 异步组件入口(dynamicImport 时使用)</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 编辑器右侧表单配置</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> value-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 组件初始值</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> event-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 组件事件 / 方法列表</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> plugin-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 插件入口</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">├──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> datasource-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 同步数据源入口</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">└──</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> async-datasource-entry.ts</span><span style="--shiki-light:#62687b;--shiki-dark:#818e99;"> # 异步数据源入口</span></span></code></pre></div><blockquote><p>详细产物说明见<a href="./publish.html#tmagic-cli">页面发布 § @tmagic/cli</a>。</p></blockquote><h2 id="playground-runtime-实现" tabindex="-1">playground runtime 实现 <a class="header-anchor" href="#playground-runtime-实现" aria-label="Permalink to “playground runtime 实现”"></a></h2><p>playground 是编辑器中央 iframe 加载的画布,最关键的逻辑就是把编辑器派发的 DSL 变更同步到本地 Vue 状态并触发重新渲染。</p><p><code>@tmagic/vue-runtime-help</code> 提供的 <code>useEditorDsl</code> Hook 已经帮我们实现了与编辑器的通信(<code>onRuntimeReady</code> / <code>updateRootConfig</code> / <code>updatePageId</code> / <code>add</code> / <code>update</code> / <code>remove</code> 等);只需要在入口里:</p><ol><li>创建 <code>TMagicApp</code> 实例,注册组件、数据源、插件;</li><li>通过 <code>provide('app', app)</code> 把实例注入子组件;</li><li>在 <code>App.vue</code> 里使用 <code>useEditorDsl()</code> + <code>useComponent('page')</code> 渲染页面。</li></ol><p>完整的 <a href="https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/playground/main.ts" target="_blank" rel="noreferrer"><code>runtime/vue/playground/main.ts</code></a>:</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;"> 'vue'</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;"> TMagicApp, { DataSourceManager, DeepObservedData } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/core'</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;"> './App.vue'</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:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/core/resetcss.css'</span><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;">DataSourceManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerObservedData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(DeepObservedData);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">Promise</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">all</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;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'../.tmagic/comp-entry'</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;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'../.tmagic/plugin-entry'</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;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'../.tmagic/datasource-entry'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">components</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">plugins</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">dataSources</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 style="--shiki-light:#c62739;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> vueApp</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>
|
||
<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:#c62739;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> TMagicApp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ua: window.navigator.userAgent,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> platform: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'editor'</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;"> (app.env.isWeb) {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setDesignWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(window.document.documentElement.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getBoundingClientRect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().width);</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;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(components.default).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">component</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 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;">]) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(type, component);</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;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(dataSources.default).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">ds</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 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;">]) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DataSourceManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">register</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(type, ds);</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;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">values</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(plugins.default).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">plugin</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 style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(plugin, { app });</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;"> window.appInstance </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app;</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.config.globalProperties.app </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app;</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">provide</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'app'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, app);</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</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;">'#app'</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><a href="https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/playground/App.vue" target="_blank" rel="noreferrer"><code>playground/App.vue</code></a> 出乎意料地短:</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;"><</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">component</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> v-if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageConfig"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> :is</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageComponent"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> :key</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageConfig.id"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> :config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageConfig"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">template</span><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;"><</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</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;">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setup</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;"> { useComponent, useEditorDsl } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/vue-runtime-help'</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;">pageConfig</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;"> useEditorDsl</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;"> pageComponent</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'page'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><div class="tip custom-block"><p class="custom-block-title">关键点</p><ul><li><code>platform: 'editor'</code> 告知 <code>@tmagic/core</code> 进入编辑模式;</li><li><code>useEditorDsl()</code> 内部已经调用 <code>window.magic?.onRuntimeReady({...})</code>,把 add/update/remove 等回调挂载到全局,编辑器通过 <code>iframe.contentWindow.magic</code> 触发;</li><li>当 DSL 变化时,<code>pageConfig</code> 自动更新;当页面 DOM 渲染完成,<code>useEditorDsl</code> 会调用 <code>magic.onPageElUpdate(...)</code> 把页面元素同步给编辑器,让选中框能够吸附。</li></ul></div><h2 id="page-runtime-实现-线上发布" tabindex="-1">page runtime 实现(线上发布) <a class="header-anchor" href="#page-runtime-实现-线上发布" aria-label="Permalink to “page runtime 实现(线上发布)”"></a></h2><p><a href="https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/page/main.ts" target="_blank" rel="noreferrer"><code>runtime/vue/page/main.ts</code></a> 与 playground 的差别在于:</p><ol><li>不需要响应编辑器消息,直接读取 <code>window.magicDSL</code>(或 <code>localPreview</code> 模式下从 <code>localStorage</code> 读取);</li><li>使用 <code>defineAsyncComponent</code> + 异步入口,按需加载组件,<strong>减小首屏体积</strong>;</li><li>数据源走 <code>registerDataSourceOnDemand</code>,只注册当前 DSL 用到的;</li><li>注入 <code>request</code> 与 <code>userRender</code> 等业务侧 API 给组件复用。</li></ol><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, defineAsyncComponent, resolveDirective, withDirectives } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'vue'</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;"> TMagicApp, { DataSourceManager, DeepObservedData, getUrlParam, registerDataSourceOnDemand } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/core'</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;"> components </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '../.tmagic/async-comp-entry'</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;"> asyncDataSources </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '../.tmagic/async-datasource-entry'</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;"> plugins </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '../.tmagic/plugin-entry'</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;"> request, { service } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './utils/request'</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;"> AppComponent </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './App.vue'</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;"> { getLocalConfig } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> './utils'</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:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/core/resetcss.css'</span><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;">DataSourceManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerObservedData</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(DeepObservedData);</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;"> vueApp</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;">(AppComponent);</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">vueApp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(request);</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;"> dsl</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ((</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getUrlParam</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'localPreview'</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;"> getLocalConfig</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;"> window.magicDSL) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [])[</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">0</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:#005CC5;--shiki-dark:#79B8FF;"> app</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> TMagicApp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ua: window.navigator.userAgent,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> config: dsl,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> request: service,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> curPage: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getUrlParam</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'page'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> useMock: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">Boolean</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getUrlParam</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'useMock'</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;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setDesignWidth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(app.env.isWeb </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> window.document.documentElement.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getBoundingClientRect</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().width </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 375</span><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;">Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(components).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">component</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 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;">]) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(type, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">defineAsyncComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(component));</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;">Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">values</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(plugins).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">plugin</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 style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(plugin, { app });</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:#6F42C1;--shiki-dark:#B392F0;">registerDataSourceOnDemand</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(dsl, asyncDataSources).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">then</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">dataSources</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 style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Object.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">entries</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(dataSources).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">forEach</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(([</span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#c13617;--shiki-dark:#FFAB70;">ds</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 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;">]) </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> DataSourceManager.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">register</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(type, ds);</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;"> vueApp.config.globalProperties.app </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app;</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">provide</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'app'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, app);</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> vueApp.</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;">'#app'</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><a href="https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/page/App.vue" target="_blank" rel="noreferrer"><code>page/App.vue</code></a> 用 <code>useDsl()</code>(注意不是 <code>useEditorDsl</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;"><</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">component</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> :is</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageComponent"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> :config</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"pageConfig as MPage"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">template</span><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;"><</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</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;">"ts"</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setup</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:#c62739;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { MPage } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/core'</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;"> { useComponent, useDsl } </span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@tmagic/vue-runtime-help'</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;">pageConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">app</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;"> useDsl</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;"> pageComponent</span><span style="--shiki-light:#c62739;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'page'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#11782a;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h2 id="vite-多入口构建" tabindex="-1">vite 多入口构建 <a class="header-anchor" href="#vite-多入口构建" aria-label="Permalink to “vite 多入口构建”"></a></h2><p><code>runtime/vue</code> 通过单个 vite 工程构建出两份产物(<a href="https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/vite.config.ts" target="_blank" rel="noreferrer"><code>vite.config.ts</code></a>):</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;">build</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> rolldownOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> input</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> page</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">resolve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(__dirname, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./page/index.html'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> playground</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: path.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">resolve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(__dirname, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./playground/index.html'</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></code></pre></div><p>加上 <code>package.json</code> 中提供的 build 脚本:</p><div class="language-json"><button title="Copy code" data-copied="Copied" class="copy"></button><span class="lang">json</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;">{</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "scripts"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "tmagic"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"tmagic entry"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "dev"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"vite --force"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "build"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"rimraf ./dist && node scripts/build.mjs --type=all"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "build:libs"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"node scripts/build.mjs --type=res"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "build:page"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"node scripts/build.mjs --type=page"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "build:playground"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"node scripts/build.mjs --type=playground"</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>最常用的两个:</p><ul><li><code>npm run build:libs</code>:构建 <strong>编辑器侧</strong>用到的 <code>config / value / event / ds-config / ds-value</code> 五份 UMD 资源(输出到 <code>dist/entry/</code>),编辑器通过 <code>asyncLoadJs</code> 异步加载(参考<a href="./#propsconfigs-propsvalues">快速开始 § propsConfigs / propsValues</a>)。</li><li><code>npm run build</code>:同时产出 <code>playground/index.html</code>、<code>page/index.html</code> 与 <code>entry/</code>,可以一份产物覆盖编辑器、预览、线上三种场景。</li></ul><h2 id="tmagic-vue-runtime-help-常用-hook" tabindex="-1">@tmagic/vue-runtime-help 常用 Hook <a class="header-anchor" href="#tmagic-vue-runtime-help-常用-hook" aria-label="Permalink to “@tmagic/vue-runtime-help 常用 Hook”"></a></h2><table tabindex="0"><thead><tr><th>Hook</th><th>作用</th></tr></thead><tbody><tr><td><code>useEditorDsl()</code></td><td>playground 入口使用,建立与编辑器通信、维护当前页面 <code>pageConfig</code></td></tr><tr><td><code>useDsl()</code></td><td>page 入口使用,从 <code>window.magicDSL</code> 中读取并维护 <code>pageConfig</code></td></tr><tr><td><code>useComponent(type)</code></td><td>通过组件 type 解析出已注册的 Vue 组件(找不到时会回退到 <code>magic-ui-${type}</code>)</td></tr><tr><td><code>useApp()</code></td><td>取出注入的 <code>TMagicApp</code> 实例</td></tr><tr><td><code>useComponentStatus()</code></td><td>获取组件在编辑器中的展示/禁用状态</td></tr></tbody></table><div class="tip custom-block"><p class="custom-block-title custom-block-title-default">TIP</p><p>React runtime 的实现思路完全一致,对应包是 <a href="https://github.com/Tencent/tmagic-editor/tree/master/runtime/react-runtime-help" target="_blank" rel="noreferrer"><code>@tmagic/react-runtime-help</code></a>,可以参照本节自行迁移。</p></div><h2 id="跨域" tabindex="-1">跨域 <a class="header-anchor" href="#跨域" aria-label="Permalink to “跨域”"></a></h2><p>playground 是被编辑器以 iframe 形式加载的,开发期需要保证 runtime 服务允许跨域。仓库里的做法是用 Vite 的 proxy 把 runtime 反代到 playground 同域:</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:#62687b;--shiki-dark:#818e99;">// playground/vite.config.ts</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">server</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> port</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">8098</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> proxy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '^/tmagic-editor/playground/runtime'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> target: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'http://127.0.0.1:8078'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
||
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> changeOrigin: </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;"> prependPath: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</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></code></pre></div><p>如果编辑器和 runtime 跨域部署,需要在 runtime 服务侧返回 <code>Access-Control-Allow-Origin</code>,并保证 iframe 的 <code>postMessage</code> 同源策略允许双方通信。</p><h2 id="进一步阅读" tabindex="-1">进一步阅读 <a class="header-anchor" href="#进一步阅读" aria-label="Permalink to “进一步阅读”"></a></h2><ul><li><a href="./conception.html">基础概念</a>:编辑器、模拟器、runtime 的关系</li><li><a href="./component.html">组件开发</a>:组件四件套(component / form-config / init-value / event)</li><li><a href="./publish.html">页面发布</a>:page.html 注入 DSL 的发布流程</li><li><a href="./tutorial/">教程</a>:从零实现一份 runtime,理解 magic API 与 DSL 解析</li></ul></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/guide/" data-v-283d6eff><!--[--><span class="desc" data-v-283d6eff>Previous page</span><span class="title" data-v-283d6eff>快速开始</span><!--]--></a></div><div class="pager" data-v-283d6eff><a class="VPLink link pager-link next" href="/tmagic-editor/docs/guide/component.html" data-v-283d6eff><!--[--><span class="desc" data-v-283d6eff>Next page</span><span class="title" data-v-283d6eff>组件开发</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> |