为复选框添加选定的期权价格 - 使用 Svelte

Adding Selected Option Prices for Checkboxes - Using Svelte

我正在尝试在选中和取消选中复选框时更新总数(以防用户改变主意不再想要该项目)。但我不确定如何获得分配给每个玩具的实际价值。例如:如果用户选择玩具 1 和 3,他们应该会看到:您订购了玩具 1、玩具 3,总价为 6.00 美元。现在我用名称本身分配了值,这不是我想要的,但我只是把它用来展示我正在尝试做的事情。他们是我应该使用的其他东西来实际执行操作以获得总数吗?

<script>
        let toylist = [];
        let toynames = [
                     'Toy1 5.00',
           'Toy2 5.00',
                     'Toy3 1.00',
        ];

        function join(toylist) {
            return toylist.join(', ');
        }
</script>
    {#each toynames as toy}
        <label>
            <input type=checkbox bind:group={toylist} value={toy}> {toy}
        </label>
    {/each}

    {#if toylist.length === 0}
        <p>Pick at least one toy</p>
     {:else}
        <p>
           You ordered {toylist.join(', ')} and your total is
        </p>
    {/if}

隔离每个玩具价格的最佳方法是将您的玩具数组变成对象数组,其中 'name' 是一个键值对,另一个是定价。对于操作数据,如果每个玩具都有一个 id 将会很有帮助,并且我已经为每个玩具添加了一个 'selected' 布尔值,如果它们被添加到 "toylist" 或从 "toylist" 中删除则更新。我还添加了一个 'total' 变量来保存所选玩具的总价格。

我已经对您的代码进行了一些尝试以完成这项工作。我使用了按钮而不是复选框,但你可以用任何你喜欢的方式来做。所以试一试这段代码,它应该会做你想做的事。

<script>
  let toylist = [];
  let toys = [
        {id: 1, name: 'Toy 1', price: 5.00, selected: false},
        {id: 2, name: 'Toy 2', price: 5.00, selected: false},
        {id: 3, name: 'Toy 3', price: 1.00, selected: false}
    ];
  let total = 0.00
  function join(toy) {
        if(toy.selected === false) {
            toylist = [...toylist, toy.name]
            total = total+toy.price
            let i = toys.findIndex(t => t.id === toy.id)
            toys[i].selected = true
            toys = toys
        } else {
            total = total-toy.price
            let i = toys.findIndex(t => t.id === toy.id)
            let i2 = toylist.findIndex(t => t === toy.name)
            toylist.splice(i2, 1)
            toylist = toylist
            toys[i].selected = false
            toys = toys
        }
  }
</script>
{#each toys as toy}
    <label>
        {toy.name}: ${toy.price} <button on:click="{() => join(toy)}" value={toy.name}>{toy.selected ? 'remove' : 'add'}</button>
    </label>
{/each}

{#if toylist.length === 0}
    <p>Pick at least one toy</p>
{:else}
    <p>
        You ordered {toylist} and your total is ${total}
    </p>
{/if}

好的,首先你应该将 toynames 数组分成一个名称和值的数组。然后你应该绑定到输入的检查属性。

为了向用户显示当前状态,我们需要一个响应式声明。让我们称之为总计。它包含两个功能。第一个返回所选名称的数组,第二个返回所选值的总和。

两者都通过查看玩具列表数组中选定的 属性 对象来工作。由于我们对 checked 属性的绑定,此更新。我创建了一个 repl 供您玩弄 ;-)

<script>
    let toylist = [
        {name: "Toy", value: 5, selected: false},
        {name: "Elephant", value: 6, selected: false}, 
        {name: "Choo-Choo", value: 1, selected: false}
    ]

  $: total = {
    names: toylist.reduce((acc, cV) => {
      if (cV && cV.selected) {
        return [...acc, cV.name];
      } else return [...acc];
    }, []),
    values: toylist.reduce((acc, cV) => {
      if (cV && cV.selected) {
        return parseInt(acc) + parseInt(cV.value);
      } else return parseInt(acc);
    }, 0)
  };

</script>
    {#each toylist as {name,value, selected}}
        <label>
            <input type=checkbox bind:checked={selected} bind:value={value}> {name}
        </label>
    {/each}

    {#if toylist.length === 0}
        <p>Pick at least one toy</p>
     {:else}
        <p>
           You ordered {total.names.length < 1 ? "nothing": total.names} and your total is {total.values}
        </p>
    {/if}

编辑: 这是具有更多经典语法的总函数:

  $: total = {
    names: toylist.reduce(function(acc, cV) {
      if (cV && cV.selected) {
        return [...acc, cV.name];
      } else return [...acc];
    }, []),
    values: toylist.reduce(function(acc, cV) {
      if (cV && cV.selected) {
        return parseInt(acc) + parseInt(cV.value);
      } else return parseInt(acc);
    }, 0)
  };

这里没有 ?运算符:

<script>
  function renderNames() {
    if (total.names.length < 1) {
      return "nothing";
    } else {
      return total.names;
    }
  }
</script>

 <p>You ordered {renderNames()} and your total is {total.values}</p>