Svelte 3: массив потомков для общения с родителями через реквизит

Svelte 3: Props и массив дочерних компонентов

Я планирую написать код настольной игры на гексагональных плитках, основанный на превосходных статьях redblobgames и написанный с помощью Svelte 3 / Sapper.

Мой вопрос касается связи между дочерними компонентами и родителями через реквизиты. Я ранее делал это в более старых версиях Svelte, используя магазин, но я думаю, что это можно сделать и без него.

Предположим, у меня есть доска из шестиугольников SVG-плиток. Everytile имеет форму:

<script>
  // 3D coordinate system, see: http://redblobgames.org for details
  export let hex = { q:0, r:0, s: 0 }    
  export let center = { x:0, y: 0 }
  export let corners = []
  export let selected = false

  let points = corners.map (c => `${c.x.toFixed(0)},${c.y.toFixed(0)}`).join (' ')

  // changed by selection process (colors...)
  let inner_class = "inner_tile"

  const toggle_select = () => {
    selected = !selected
  }
</script>

<g class="tile" on:click="[ () => toggle_select() }"
  <polygon class={ inner_class} [ points } />

  <!-- more sophisticated things -->
  <!-- sprites, lbels, masks and animations  -->

</g>

Компонент Editor отвечает за выбор макета из моей пользовательской реализации библиотеки обработки шестиугольника redblobgames, настройку контейнера SVG и заполнение сетки плитками. Это просто каждый оператор, вызывающий компонент Hex:

<svg 
  xmlns="www.w3.org/2000/svg"
  viewBox="-50 -50 589 949" 
  width="420"
  height="500"
>
  <!-- just a debugging purpose rectagle ! -->
  <rect x="0" y="0" width="400" height="500" style="fill: none; stroke: black;"/>


  <g class="tiles">
    {#each tiles  as tile }
      <Hex {...tile} />
    {/each}
  </g>  
</svg>

<!-- this helping zone keeps empty, sadly, whatever I attempt to do -->  
<textarea cols="50" rows="10">
  { selected_tiles_output }
</textarea>

Проблема возникает при попытке отобразить ссылки на выбранные плитки (q, r, s) в текстовой области под доской. Doinfg в сценарии не работает:

// imports...

let tiles = []
let selected_tiles = new Set ()
let selected_tiles_output = ''

// onMount to assemlble the board ...

// reactive part which doesn't work:
$: selected_tiles_ouptut = tiles
  .filter (tile => tile.selected)
  .map (tile => tile.hex)
  .map (h => `q: ${h.q}, r: ${h.r}, s: ${h.s} \n`)
  .reduce ((acc, val) => acc + val, '')

ВОПРОС:

Может ли родительский контейнер наблюдать определенное свойство (также известное как «selected») в массиве childfren, своего рода «каррирование» свойств в дочернем компоненте?

  • OR -

стоит ли мне наконец подумать об использовании магазина для этого?

ПРИМЕЧАНИЕ: на данном этапе разработки мне сложно поделиться каким-либо полным образцом рабочего кода или исходным кодом, поскольку он сильно меняется. В худшем случае я могу заархивировать и отправить по почте папки src / routes и src / components sapper!

Есть ли у кого-нибудь идея отпустить меня по правильному пути?

С уважением, hefeust.


person Hefeust    schedule 01.10.2019    source источник


Ответы (1)


Вы можете настроить получение одним из родителей реактивных обновлений от дочернего элемента с помощью директивы bind: - см. Документы здесь

Похоже, вы могли бы привязать плитки при передаче их на гексы, примерно так:

{#each tiles as {hex, center, corners, selected} }
  <Hex {hex} {center} {corners} bind:selected />
{/each}

А затем Editor.svelte должен получать обновления при изменении tile.selected в Hex.svelte.


В качестве альтернативы вы можете определить toggle_select в родительском Editor вместо Hex и передать его как опору в Hex. Таким образом, обновление плиток происходит прямо в Editor:

<!-- Editor.svelte -->
  <g class="tiles">
    {#each tiles  as tile }
      <Hex {...tile} toggle_select={() => tile.selected = !tile.selected} />
    {/each}
  </g>  
<!-- Hex.svelte -->
<script>
  export let toggle_select

Надеюсь, это поможет!

person will_wow    schedule 01.10.2019
comment
Упс .. да! директива bind ... хороший ответ! большое спасибо ;-) - person Hefeust; 01.10.2019