【问题标题】:Computed values in a object | Svelte对象中的计算值 |苗条
【发布时间】:2019-12-09 23:54:58
【问题描述】:

我正在编写一些项目来学习 Svelte,并且我一直在尝试制作类似于电子表格的东西,其中用户键入或更改数字并使用预定义的公式进行一些微积分(用户无法更改公式)。我已经尝试过了,但我不能被动地做到这一点。

为此,我创建了一个名为 Spreadsheet 的组件,它有两个 props,即数据和列,类似于 Quasar 为 Tables 所做的事情。

Here 是示例的 REPL。

这个想法是用户更改 females, males and area 列上的值,然后使用 poblationDensity 公式反应性地更改 density 列的值。

/* App.svelte */
<script>
  import Spreadsheet from "./Spreadsheet.svelte";

    const poblationDensity = (females, males, area) => {
    return (females + males) / area;
  };

  let data = [
        {
      "id": 1,
      "animal": "White-mantled colobus",
      "females": 13,
      "males": 33,
      "area": 109
    },
    {
      "id": 2,
      "animal": "Woodpecker, red-headed",
      "females": 99,
      "males": 88,
      "area": 252
    },
    {
      "id": 3,
      "animal": "White-necked raven",
      "females": 34,
      "males": 36,
      "area": 362
    },
    {
      "id": 4,
      "animal": "Baleen whale",
      "females": 24,
      "males": 67,
      "area": 457
    },
    {
      "id": 5,
      "animal": "Tiger",
      "females": 89,
      "males": 20,
      "area": 476
    },
    {
      "id": 6,
      "animal": "White spoonbill",
      "females": 56,
      "males": 85,
      "area": 358
    },
    {
      "id": 7,
      "animal": "Giant anteater",
      "females": 83,
      "males": 98,
      "area": 236
    },
    {
      "id": 8,
      "animal": "White-fronted capuchin",
      "females": 72,
      "males": 44,
      "area": 163
    },
    {
      "id": 9,
      "animal": "Raccoon, crab-eating",
      "females": 78,
      "males": 61,
      "area": 410
    },
    {
      "id": 10,
      "animal": "Turtle, long-necked",
      "females": 5,
      "males": 77,
      "area": 472
    }
    ];

  const cols = [
    {
      name: "id",
      label: "#"
    },
    {
      name: "animal",
      label: "Animal"
    },
    {
      name: "females",
      label: "Females"
    },
    {
      name: "males",
      label: "Males"
    },
    {
      name: "area",
      label: "Area"
    },
    {
      name: "density",
      label: "Density",
      computed: {
        args: ["females", "males", "area"],
        method: poblationDensity
      }
    }
  ];
</script>

<main>
    <Spreadsheet {data} {cols} />
</main>
/* Spreadsheet.svelte */
<script>
    export let data = [];
  export let cols = [];
</script>

<style>
    .numeric {
        width: 70px;
    }
</style>

<table>
    <tr>
        {#each cols as col}
        <th>{col.label}</th>
        {/each}
    </tr>
    {#each data as item}
    <tr>
        {#each cols as col}
            <td>
                <input type="text" class="{col.name !== 'animal' && 'numeric' }"
                             value={col.computed ? 0 : item[col.name]} 
                />
                </td>
        {/each}
    </tr>
    {/each}
</table>

【问题讨论】:

标签: javascript spreadsheet svelte svelte-component


【解决方案1】:

很好的例子!

首先要做的是将您的计算功能,即poblationDensity,实际连接到显示的内容。我们可以像这样更改&lt;input &gt; 字段的值:

value={col.computed ? col.computed.method(item) : item[col.name]}

我已经稍微调整了你的函数来完成这项工作:

const poblationDensity = ({ females, males, area }) => {
  return (females + males) / area;
};

有了这个,我们得到了正确的显示。现在我们需要获取这些值。

在 Svelte 中,获取 &lt;input /&gt; 值的最常用方法是 two-way binding。它也适用于对象属性!

在我们的例子中,我们需要绑定到字段的值,所以bind:value={...}。让我们将其添加到我们的示例中。为此,我们需要为只读(计算)值分离标记:

{#if col.computed}
  <input
    type="text"
    class={col.name !== 'animal' && 'numeric'}
    value={col.computed.method(item)} />
{:else}
  <input
    type="text"
    class={col.name !== 'animal' && 'numeric'}
    bind:value={item[col.name]} />
{/if}

还有……好吧,我们到了!缺失完成! Updated REPL

每次更新值时,bind:value 都会在 data 数组中更新它。 Svelte 知道此更改并相应地重新呈现受影响的行。此时,计算值被重新计算。

另一种方法是使用一个中间数组来保存计算值。为此,Svelte 提供reactive declarations & statements。起初,它们的外星外观让它们有点吓人,但一旦你习惯了它们,它们就会像魔法一样!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-24
    • 2012-12-01
    • 2020-08-05
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    相关资源
    最近更新 更多