切换页面时 Svelte 组件出错

Error in Svelte component when switching pages

我有一个使用 Svelte + Laravel + Inertia 的项目,我正在处理一个具有记录分页功能的页面。 但是当我更改页码时,控制台中会显示错误并且应用程序停止工作。

app.js:108643 
        
       Uncaught (in promise) TypeError: Cannot read properties of null (reading 'removeChild')
    at detach (app.js:108643:19)
    at Object.d (app.js:83321:77)
    at Object.d (app.js:83428:16)
    at destroy_component (app.js:110453:32)
    at Object.d (app.js:81565:73)
    at Object.d (app.js:80366:38)
    at destroy_component (app.js:110453:32)
    at Object.d (app.js:81393:73)
    at Object.d (app.js:81640:43)
    at destroy_component (app.js:110453:32)

经过一些测试,我发现了问题: 在我的组件中,我有 Inertia Link 组件,它导致了错误,因为如果我将组件更改为简单标记,错误就会停止。

组件代码

<script>
    import { onMount } from "svelte";
    import { Link } from "@inertiajs/inertia-svelte";
    import { icon as make } from "@fortawesome/fontawesome-svg-core";
    export let icon, title, click, attributes, href;

    const svg_uid = Math.random().toString(16).substring(2);

    onMount( () => {
        const svg = make(icon).node[0];
        document.querySelector(`svg[data-fa-svg="${svg_uid}"]`).replaceWith(svg);
        const button = svg.parentElement;
        for (const attribute in attributes) {
            button.setAttribute(attribute, attributes[attribute])
        }
    })
</script>
<!--
    ---------------------------------------
    HTML Template
    ---------------------------------------
-->
{#if click}
    <button type="button" {title} class="svg-button-component" on:click={click}>
        <svg data-fa-svg="{svg_uid}"></svg>
    </button>
{:else if href}
    <Link {href} {title}>
        <svg data-fa-svg="{svg_uid}"></svg>
    </Link>
{:else}
    <svg data-fa-svg="{svg_uid}"></svg>
{/if}

工作代码(感谢@dummdidumm)

<script>
    import { onMount } from "svelte";
    import { icon as make } from "@fortawesome/fontawesome-svg-core";
    import { Link } from "@inertiajs/inertia-svelte";

    export let icon, button, href;

    const uid = Math.random().toString(16).substring(2);
    onMount( () => {
        if (href) {
            document.querySelector(`a[data-fa-svg="${uid}"]`)
                .appendChild(
                    make(icon).node[0]
                )
        } else {
            document.querySelector(`svg[data-fa-svg="${uid}"]`)
                .replaceWith(
                    make(icon).node[0]
                )
        }
    })
</script>
<!--
    ---------------------------------------
    HTML Template
    ---------------------------------------
-->
{#if button}
    <button type="button" {...$$restProps} class="svg-button-component" on:click>
        <svg data-fa-svg="{uid}"></svg>
    </button>
{:else if href}
    <Link {href} {...$$restProps} data-fa-svg={uid}></Link>
{:else}
    <svg data-fa-svg="{uid}" {...$$restProps}></svg>
{/if}

问题不在于 Link 组件,而是代码强制性地将 svg 元素替换为不同的元素。 Svelte 不知道这一点,并保留对作为 Link 子元素的旧(现已删除)svg 元素的引用。当组件被销毁时,它会尝试删除那个不存在的元素,因此会抛出错误。要么你调整你的代码而不是强制修改代码,要么你在你替换的元素周围添加一个包装元素,比如

<Link>
  <span>
    <svg ...>
  </span>
</Link>