Svelte递归组件编译为自定义Web组件时实例化错误求助
Svelte自定义元素递归渲染报错解决
问题
用递归构建树形视图,普通Svelte环境运行正常,但编译为自定义Web组件(开启customElement:true并配置tag)时,出现运行时错误:
Uncaught TypeError: Cannot instantiate a custom element inside its own constructor during upgrades
原代码示例:
<svelte:options tag="my-tree" /> <script> export let arraytree; export let level = 0; let aTree = JSON.parse(arraytree); </script> {#each aTree as branch} {#if Array.isArray(branch)} <svelte:self arraytree={JSON.stringify(branch)} level={level + 1}/> {:else} <p>branch</p> {/if} {/each}
原因
这不是Svelte的通用限制,而是浏览器自定义元素规范的约束:自定义元素的构造函数(或升级过程中)不允许实例化同一个自定义元素,否则会触发递归实例化的循环,浏览器会直接抛出错误。而<svelte:self>在自定义元素模式下,会直接实例化当前自定义元素,刚好触发了这个限制。
解决方法
把递归逻辑拆分到内部普通Svelte组件中,自定义元素只作为外层容器传递数据,避免在自定义元素构造时实例化自身。
修改后的代码
- 新建内部递归组件
MyTreeInner.svelte
<script> export let treeData; export let level = 0; </script> {#each treeData as branch} {#if Array.isArray(branch)} <MyTreeInner treeData={branch} level={level + 1} /> {:else} <p>branch</p> {/if} {/each}
- 修改自定义元素组件
my-tree.svelte
<svelte:options tag="my-tree" /> <script> import MyTreeInner from './MyTreeInner.svelte'; export let arraytree; let treeData = JSON.parse(arraytree); </script> <MyTreeInner treeData={treeData} />
这样处理后,内部递归由普通Svelte组件完成,不会触发自定义元素的实例化逻辑,外层自定义元素只做一次初始化,完美避开浏览器的限制。
内容的提问来源于stack exchange,提问作者tue
相关产品推荐
相关产品推荐

