You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte绑定实体的Proxy数组无法修改的问题及优化咨询

Svelte可绑定属性修改不生效问题:Proxy数组无法添加元素

我在Svelte组件中通过属性派生变量:

let {entity = $bindable(), targetType}: { entity: EntityDTO, targetType: EntityType } = $props();
const links = $derived(entity.links?.filter(link => link.entityB.type === targetType) || []);

随后编写了向实体添加链接的函数:

function addLink(article: EntityDTO, link: EntityDTO): EntityDTO {
    const toReturn = addEntityLink(article, link, LinkType.REFER, LinkState.APPROVED);
    isFocused = false;
    return toReturn;
}

其中addEntityLink是工具库函数,会在特定条件下向links属性push新链接:

console.log( "adding", newLink );
sourceEntity.links.push(newLink);
console.log( "after adding", sourceEntity );

问题现象

执行push后日志显示链接并未被添加:

after adding { _id: 'entity1', links: [] }

检查发现links是Proxy(Array)类型,但工具代码不应感知这种数组不可变的情况。


无效尝试

尝试通过重新创建对象规避Proxy行为,但问题依旧:

function addLink(entity: EntityDTO, link: EntityDTO): EntityDTO {
    entity.links = [...(entity.links || [])] // 尝试规避Proxy行为
    const toReturn = addEntityLink(entity, link, LinkType.REFER, LinkState.APPROVED);
    isFocused = false;
    entitySuggestions = filterAlreadyLinked(lastSuggestions, links);
    entity = toReturn;
}

调试器中links仍为Proxy(Array)类型,日志依旧显示未添加链接。

异常日志

修改工具代码为以下形式后:

console.log( "adding", newLink, " to ", typeof sourceEntity.links);
const links = [...sourceEntity.links, newLink];
sourceEntity.links = links;
console.log( "links: ", links );
console.log( "after adding", sourceEntity );

输出异常日志:

links:  [
  {
    entityAType: undefined,
    entityAId: 'entity1',
    entityBType: undefined,
    entityBId: 'lib1',
    entityB: {
      _id: 'lib1',
      name: 'React Library',
      icon: 'react.png',
      categories: [Array],
      summary: 'A popular UI library'
    },
    state: 'approved',
    type: 'refer'
  }
]
after adding { _id: 'entity1', links: [] }

推测由于entity是可绑定属性,对其属性的修改未生效。


核心问题

  • 如何在组件中隔离Proxy相关逻辑,避免样板代码降低可读性?
  • 如何解决当前链接无法添加的问题?

重要说明

代码在浏览器中可正常运行,但测试用例失败:

it('adds a library to an article', async () => {
    // 创建可追踪的模拟实体对象
    const testEntity = {
        _id: 'entity1',
        links: []
    };
    const { component } = render(EntityLinkSelector, {
        props: {
            entity: testEntity,
            targetType: EntityType.LIBRARY
        }
    });

    const input = await screen.findByTestId('search-input');

    // 1. 先聚焦输入框(对isFocused状态至关重要)
    await fireEvent.focus(input);
    await tick();

    // 2. 输入内容(触发searchQuery更新)
    await fireEvent.input(input, { target: { value: 'react' } });

    // 3. 等待防抖和请求完成
    // await new Promise(resolve => setTimeout(resolve, 350));
    await tick();

    // 查找弹出框
    const suggestionsPopover = await screen.findByTestId('suggestions-popover');
    // 在弹出框内找到建议项
    const suggestion = within(suggestionsPopover).getByText('React Library');
    await fireEvent.click(suggestion);
    await tick();

    // 验证建议项已从弹出框中移除
    expect(within(suggestionsPopover).queryByText('React Library')).not.toBeInTheDocument();

    // 验证链接已添加到相关链接区域
    const relatedLinksSection = await screen.getByTestId('related-links');
    expect(within(relatedLinksSection).getByText('React Library')).toBeInTheDocument();

})

内容的提问来源于stack exchange,提问作者Zied Hamdi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:42:15