簡體   English   中英

在 Svelte 中是否有可能使 #each 循環具有雙向綁定到嵌套的 object 值?

[英]Is it possible in Svelte to have #each loops with two-way binding to nested object values?

以下 Svelte 代碼運行良好:

<input bind:value='options.name.value' placeholder='{{options.name.placeholder}}'>
<p>Hello {{options.name.value || 'stranger'}}!</p>

使用這個 JSON:

{
    "options": {
        "name": {
            "value": "",
            "placeholder": "enter your name"
        }
    }
}

您可以看到它的實際效果 但是,如果我們想使用#each數組遍歷options怎么辦……這可能嗎?

如果我們做除了綁定之外的所有事情,它幾乎可以工作:

{{#each Object.keys(options) as option}}
<input bind:value='options.name.value' placeholder='{{options[option].placeholder}}'>
<p>Hello {{options[option].value || 'stranger'}}!</p>
{{/each}}

可以看到占位符是正確的,雙向綁定工作正常。 但是代碼還不正確,因為options.name是為綁定而硬編碼的,而不是使用循環值。 如果我們嘗試修復它,放置bind:value='options[option].value' ,我們會得到一個語法錯誤, Expected '

那么,如果可以使用循環值在循環內進行雙向綁定,那么正確的語法是什么?

簡短的回答是,是的,絕對可以在each塊內使用雙向綁定,但塊的值必須是一個簡單的數組,而不是像Object.keys(options)這樣的表達式的結果:

{#each options as option}
  <input bind:value={option.value} placeholder={option.placeholder}>
{/each}
{
  "options": [
    {
      "id": "name",
      "value": "",
      "placeholder": "enter your name"
    },
    {
      "id": "email",
      "value": "",
      "placeholder": "enter your email"
    }
  ]
}

更長的答案,我在其中大聲思考了一會兒:使用表達式(不僅僅是像foo這樣的引用或像foo.bar這樣的非計算成員表達式)進行雙向綁定是一個有趣的挑戰。 實際上有兩個獨立的問題:首先,區分像options[option].value這樣的有效表達式和在雙向綁定上下文中沒有任何意義的表達式。 其次, each塊表達式創建了一種障礙——如果有人要這樣做......

{#each Object.keys(options) as option}
  <input bind:value={option}>
{/each}

...它們將綁定到一個本質上是只讀的值。 但是你不能僅僅從語法上看出這一點。 所以靜態分析需要足夠聰明才能理解綁定到options[option].name是有效的,但綁定到option不是。 值得我們思考的東西。

最后,秘密選項不在此上下文中使用雙向綁定,因為它實際上只是一個方便的事件偵聽器包裝器:

<script>
  let options = {
    name: {
      value: '',
      placeholder: 'enter your name'
    }
  };

  function updateValue(option, value) {
    options[option].value = value;
  }
</script>

{#each Object.keys(options) as option}
  <input
    on:input="{() => updateValue(option, e.target.value)}"
    placeholder={options[option].placeholder}
  >
{/each}
 <script>
  let options = {
    name: {
      value: '',
      placeholder: 'enter your name'
    },
  };
    
    $: console.table(options)
</script>

{#each Object.entries(options) as [key, option]}
  <input
    bind:value={option.value}
    placeholder={option.placeholder}
  >
{/each}

https://svelte.dev/repl/a77dd18da023469da962d873e6fb391f?version=3.47.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM