Svelte 3: массив потомков к родительскому общению через реквизит - PullRequest
0 голосов
/ 01 октября 2019

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

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

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

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

<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>

Компонент «Редактор» отвечает за выбор макета из моей пользовательской реализации библиотеки обработки шестиугольников redblobgames, настройку контейнера SVG и заполнение сетки плитками. Tis - это просто каждое утверждение, вызывающее компонент 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, что-то вроде «карри» в дочернем компоненте?

  • ИЛИ -

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

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

У кого-нибудь есть идея, чтобы я пошел по правильному пути?

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

1 Ответ

2 голосов
/ 01 октября 2019

Родитель может получать реактивные обновления от ребенка, используя директиву 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

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

...