Svelte每个工作两次/每个绑定错误(不能设置未定义的属性) [英] Svelte each worked twice / each binding error ( Cannot set properties of undefined )

查看:18
本文介绍了Svelte每个工作两次/每个绑定错误(不能设置未定义的属性)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绑定{#each}块中的元素,并通过单击删除它们。

    <script>
        const foodList = [
          { icon: '🍲', elem: null, },
          { icon: '🥫', elem: null, },
          { icon: '🍔', elem: null, },
        ]; 
        const remove = (index) => { 
          foodList.splice(index, 1);
          foodList = foodList;
        };
    </script>

    {#each foodList as {icon, elem}, index}
      <div 
        bind:this={elems[index]}
        on:click={remove}
      >
        {icon}
      </div>
    {/each}

在我的代码中有两个问题:

  • {#each}使迭代次数增加两倍
  • 通过单击绑定的元素删除数组中的项后-svelte触发错误&无法设置未定义&的属性

为什么是这样工作的?

推荐答案

我写这篇文章不是为了寻求帮助,而是为了帮助那些遇到同样问题的人

这两个问题都有相同的根源,所以我在这里收集它们:

  • 有时{#each}块的工作比预期的多两倍
  • 有时{#each}阻止绑定引发错误

在Svelte编译器3.44.1版中测试的所有代码


问题1-每个人工作两次

我是什么意思?

  • 每个块进行两次所有迭代

让我告诉您,看看下面的代码,{#each}可以迭代多少次?

<script>
  const foodList = [
        { icon: '🍲' },
        { icon: '🥫' },
        { icon: '🍔' } 
  ]; 
</script>

{#each foodList as {icon}}
  <div> {icon} </div>
{/each}

如果您的答案是-3,那么恭喜您,您是对的。

好的,现在我们需要绑定我们在{#each}块中呈现的元素。

这是相同的代码,只是在{#each}

中为每个div绑定的对象添加了适当的‘elem’

请查看下面,然后重试,{#each}需要迭代多少次?

<script>
  const foodList = [
        { icon: '🍲', elem: null, },
        { icon: '🥫', elem: null, },
        { icon: '🍔', elem: null, } 
  ]; 
</script>

{#each foodList as {icon, elem} }
  <div 
    bind:this={elem}
   > 
     {icon} 
   </div>
{/each}

对……我们有6次迭代,两次更多。

首先添加一些console.log(){#each}块代码即可看到,如下所示:

{#each foodList as {icon, elem}, index}
  {console.log('each iteration: ', index, icon) ? '' : ''}
  <div 
    bind:this={elem}
   > 
     {icon} 
   </div>
{/each}

这是因为我们对{#each}迭代和绑定使用了相同的数组

如果我们创建用于绑定的新数组问题将消失

<script>
  const foodList = [
        { icon: '🍲' },
        { icon: '🥫' },
        { icon: '🍔' } 
  ]; 
  const elems = [];
</script>

{#each foodList as {icon}, index }
  { console.log('each iteration: ', index, icon) ? '' : ''}
  <div 
    bind:this={elems[index]} 
   > 
     {icon} 
   </div>
{/each}

对..。现在问题解决了,我们得到了3次迭代,正如我们预期的
正如我试图找出的那样,这是一个活了很长时间的细菌--至少一年。随着OUT代码变得更加复杂,这会在不同的情况下导致不同的问题。


问题2-在对可迭代数组进行切片后,每个绑定都会引发错误

(类似于:‘无法设置未定义的属性’)

我是什么意思?

  • 在删除一个可迭代数组项后,每个块绑定都会引发错误

相同的示例,只是在其元素上添加了删除数组项点击:

<script>
    const foodList = [
        { icon: '🍲', elem: null, },
        { icon: '🥫', elem: null, },
        { icon: '🍔', elem: null, }  
    ]; 
    
    const remove = (index) => { 
        foodList.splice(index, 1);
        foodList = foodList;
    };
</script>

{#each foodList as {icon, elem}, index} 
    {console.log('each iteration: ', index, icon) ? '' : ''} 
    <div 
        bind:this={elem}
        on:click={remove}
    >
        {icon}
    </div>
{/each}
我们预计,如果我们单击div-数组项,它绑定到的数组项将被切片,我们将在屏幕上丢失它们。正确..。但我们得到了错误,因为{#each}块使仍然是3次迭代,而不是我们等待的2次迭代。

同样为了清晰起见,我们的代码步骤是:foodList长度为3->;我们点击食物图标->;foodList长度为2(我们用点击的图标剪切项目)。

之后{#each}应该重复2次以呈现foodList中的每个左侧图标,但他却重复了3次!

这就是我们遇到问题的原因,我们的代码试图将新属性写入未定义的(项被切片,因此当我们尝试读写它时-存在未定义的。

//食品列表[{ICON:‘🍲’,elem:空,},{ICON:‘🥫’,elem:空,}]
FoodList[2].elem=<;div>;;//";无法设置未定义的

的属性

这是一个错误,如果我们对{#each}迭代和绑定使用相同的数组,则会发生错误。

对我的问题最干净利落的解决办法是将可迭代数据和绑定数据分离到不同的数组中:

<script>
    const foodList = [
        { icon: '🍲' },
        { icon: '🥫' },
        { icon: '🍔' }  
    ]; 
    let elems = [];
    
    const remove = (index) => { 
        foodList.splice(index, 1);
        foodList = foodList;
    };
      
    
</script>

{#each foodList as {icon, cmp}, index} 
    {console.log('each iteration: ', index, icon) ? '' : ''} 
    <div 
        bind:this={elems[index]}
        on:click={remove}
    >
        {icon}
    </div>
{/each}

但是...让我们通过添加$: console.log(elems);

来查看新的elems数组

(它是反应式表达式,每次更改时都会打印elems数组)

<script>
    const foodList = [
        { icon: '🍲' },
        { icon: '🥫' },
        { icon: '🍔' }  
    ]; 
    let elems = [];
    
    const remove = (index) => { 
        foodList.splice(index, 1);
        foodList = foodList;
    };
      
    $: console.log(elems);  
</script>

{#each foodList as {icon, cmp}, index} 
    {console.log('each iteration: ', index, icon) ? '' : ''} 
    <div 
        bind:this={elems[index]}
        on:click={remove}
    >
        {icon}
    </div>
{/each}

看起来像是有两条新闻要告诉您

  • 我们没有收到错误
  • 我们在elems数组中有新的null

这意味着问题仍然存在({#each}块仍然使切片项多迭代一次)。

目前我们可以在foodList切片后过滤elems数组,只能在页面更新后进行,如tick()

完整代码:

<script>
    import { tick } from 'svelte';
    
    const foodList = [
        { icon: '🍲', elem: null, },
        { icon: '🥫', elem: null, },
        { icon: '🍔', elem: null, } 
    ]; 
    let elems = [];
    
    const remove = async (index) => { 
        foodList.splice(index, 1);
        foodList = foodList;
        await tick();
        elems = elems.filter((elem) => (elem !== null)); 
    };
    
    $: console.log(elems);  
</script>

{#each foodList as {icon, elem}, index}
    {console.log('each iteration: ', index, icon) ? '' : ''}
    <div 
        bind:this={elems[index]}
        on:click={remove}
    >
        {icon}
  </div>
{/each}

请记住{#each}块仍然可以额外工作1次,我们的绑定元素为空,我们只是在页面更新后对其进行了筛选。

最后一站

真的不知道该说什么.我在这上面浪费了太多时间*试图找出为什么我的代码不能正常工作。

我喜欢苗条,但我不喜欢虫子

我真的希望这本小指南能帮助你们中的一些人节省很多时间。

将很高兴看到您的更正,再见,不要让🐞获胜。

P.S.

是的,这需要时间,但是..。永远不知道什么时候需要帮助,分享你的知识

这篇关于Svelte每个工作两次/每个绑定错误(不能设置未定义的属性)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆