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

Posted

技术标签:

【中文标题】使用 JavaScript 创建的 Svelte 组件不接收响应式更新【英文标题】:Svelte component created with JavaScript not receiving reactive updates 【发布时间】:2021-08-24 03:38:26 【问题描述】:

我使用以下 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 创建时,该更新按指定工作。

【问题讨论】:

你是如何动态插入的?你能更新你的帖子来显示这个吗? @Kwright02 我已经更新了代码以显示如何在点击时插入组件 “更新订单道具”代码是什么样子的? @dummdidumm 按要求添加了代码 【参考方案1】:

我不知道您的更新函数的上下文是什么以及它位于/调用的位置,但是当以编程方式/命令式创建组件时,通过赋值触发重新渲染不起作用。相反,您需要在组件实例上使用$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>

【讨论】:

【参考方案2】:

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

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

通常,在 Svelte 中,您不会使用现有的代码。一种更Svelte的方法是使用布尔值来跟踪是否必须显示模态:

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

#if showModal
  <Modal />
/if

【讨论】:

这是公平的,我在直接添加模态时所做的事情。我仍然想知道是否有办法在编译后更新反应链接。 afaik 仅当您使用商店时,因为编译器是安排反应性的人

以上是关于使用 JavaScript 创建的 Svelte 组件不接收响应式更新的主要内容,如果未能解决你的问题,请参考以下文章

如何手动将 svelte 组件编译为 sapper/svelte 生成的最终 javascript 和 css?

在 svelte 中导入 javascript 文件

给新手开发者的 Svelte 教程

javascript Svelte中的编译变量修改

javascript 在Svelte没有州的Redux

javascript Svelte DOM Element Creator