Можно ли сделать дочерний компонент внутри слота для отправки данных его родителю? - PullRequest
1 голос
/ 02 июля 2019

Я пытаюсь создать компонент формы в Sveltejs.Этот компонент формы будет использовать <slot />, чтобы его родитель (App.svelte) определил, какие входы и кнопки должны быть внутри формы.Inputs и Buttons также являются компонентами, и после изменения значения компонента Input я хотел бы обновить объект внутри родительского компонента Form, а когда нажата кнопка, я хотел бы отправить данные обратно в компонент App.

Я пытался прочитать документацию Svelte и решить эту проблему, играя с <slot let:name={value}>, но не могу найти способ обновить компонент Form при изменении значения компонента Input.

Это структура того, чтоЯ пытаюсь сделать:

App.svelte

...
<Form on:submit={saveReceivedData}>
  <Input name="..." value="..." />
  <Button />
</Form>
...

Form.svelte

<script>
...
let data = {}
</script>
...
<form>
  <slot />
</form>
...

Input.svelte

...
<input name={name} value={value} on:input={updateDataVariableOnFormComponent} />
...

Кнопка.svelte

...
<button on:click={sendDataVariableToAppComponent}>Send</button>
...

Я могу попытаться отправить вам полный код, если это необходимо.Но, поскольку моя проблема не в том, «что я делаю неправильно?»но «как я могу это сделать?», я предпочитаю писать мой вопрос абстрактно.

Ответы [ 2 ]

2 голосов
/ 02 июля 2019

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

<Input name="..." bind:value={someValue} />

С этой привязкой someValue в родительском элементе будет синхронизироваться с value в дочернем.

Чтобы уведомить родителя о событиях в дочернем элементе, в отличие от изменений состояния, вы можете использовать диспетчер событий ...

<!-- Button.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
</script>

<button on:click={() => dispatch('thinghappened', someData)}>Send</button>

... в этом случае вы можете прослушать событие thinghappened ...

<Button on:thinghappened={e => doSomethingWith(e)}/>

... или вы можете просто переслать событие DOM с помощью <button on:click>Send</button> и прослушать событие click у родителя с помощью <Button on:click={handler}/>.

0 голосов
/ 03 июля 2019

Это то, что я хотел сделать. Я, честно говоря, не на 100% доволен этим, но я люблю Svelte: D

App.svelte

<script>
    import Form from "./Form.svelte"
    import Input from "./Input.svelte"
    import Button from "./Button.svelte"
    let data = {
        name: "John",
        surname: "Smith"
    }
    const saveValues = (event) => {
        data = event.detail
    }
</script>

<Form data={data} let:saveMe let:updateMe on:save={saveValues}>
    <Input
        label="Name"
        name="name"
        value={data.name}
        on:input={updateMe}
    />
    <Input
        label="Surname"
        name="surname"
        value={data.surname}
        on:input={updateMe}
    />
    <Button on:click={saveMe}>
        Save
    </Button>
</Form>

<h4>Saved data</h4>
<ul>
    {#each Object.entries(data) as d}
        <li>{d[0]}: {d[1]}</li>
    {/each}
</ul>

Form.svelte

<script>
    import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
    export let data;
    const saveMe = () => dispatch('save', data)
    const updateMe = (e) => data = {...data, [e.detail.name]: [e.detail.value]}
</script>

<slot saveMe={saveMe} updateMe={updateMe} />

Input.svelte

<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  export let name;
  export let label = false;
    export let value = "";
</script>

<div class="input-field">
  <input
    id={name}
    name={name}
    value={value}
        on:input={(e) => {
      value = e.target.value
      dispatch('input', e.target)
    }}
  />
  {#if label}
    <label
      for={name}
      class:active={value.length > 0}
    >{label}</label>
  {/if}
  <slot />
</div>

Button.svelte

<button on:click>
    <slot />
</button>
...