使用 JavaScript 创建的 Svelte 组件未接收到响应式更新

Svelte component created with JavaScript not receiving reactive updates

我使用以下 JS 在单击按钮时动态创建一个组件:

<script>
    export let order;

    function toggleModal(an_order){
        modal_open.set(!$modal_open);
        const modal = new OrderModal({
            target: document.querySelector('.modal_container-' + order.id),
            props: {
                order: an_order
            },
        });
    }
</script>

但是,每当我更新订单对象时,它都不会反应性地反映在创建的组件中。

如果我将组件直接放在 html 中而不是像这样使其动态化:

<div class="modal_container-{order.id} fixed">
    <OrderModal {order} />
</div>

<div class="max-w-xs w-full overflow-hidden rounded-lg shadow-md bg-white cursor-pointer" on:click="{() => toggleModal(order)}">

然后它可以正常工作,并且元素会被反应更新。

有没有办法让 JavaScript 创建的组件响应式更新?

*** 正在更新以显示其插入方式 ***

执行更新的函数:

function deleteItem(){
  order.order_items.splice(index, 1);
  $order_list = $order_list;
}

如您所见,我明确地做了一个分配来触发更新,当组件不是通过 javascript 创建时,该更新按指定的方式工作。

这不起作用的原因是编译器将在编译期间创建反应元素之间的所有链接。您的 Modal 组件当时不存在,因此不可能这样做。这也解释了为什么直接添加Modal就可以了。

解决此问题的一种方法是使用商店并将该商店传递到模式中。

一般来说,在 Svelte 中,您不会直接使用代码。一种更 Svelte 的方法是使用 bool 来跟踪是否必须显示模态框:

<script>
  let showModal = false
  function toggleModal() {
    showModal = !showModal
  }
</script>

{#if showModal}
  <Modal />
{/if}

我不知道您的更新函数的上下文是什么以及它 located/called 来自哪里,但是在创建组件 programmatically/imperatively 时,通过赋值触发重新渲染不起作用。相反,您需要在组件实例上使用 $set 方法(文档:https://svelte.dev/docs#$set):

<script>
    export let order;

    let modal; // <- top level variable so it can be used in the update function
    function toggleModal(an_order){
        modal_open.set(!$modal_open);
        modal = new OrderModal({
            target: document.querySelector('.modal_container-' + order.id),
            props: {
                order: an_order
            },
        });
    }

    // ...
    function deleteItem(){
        order.order_items.splice(index, 1);
        // imperatively update the order
        modal.$set({order: $order_list});
    }

    // if you want updates of the `order` prop to propagate to the modal once it's set, you can do
    $: modal && modal.$set({order: order});
</script>