Я работаю над созданием многошаговой формы с использованием Svelte.js, но столкнулся с проблемой рендеринга каждой страницы формы с уникальными реквизитами.
Вот простая демонстрация, чтобы показать вам, что я имею в виду:
// App.svelte
<script>
import FormPage from "./FormPage.svelte";
let formNode;
let pageSelected = 0;
let formPages = [
{
name: "email",
label: "Email"
},
{
name: "password",
label: "Password"
}
];
const handleIncPage = () => {
if(pageSelected + 1 < formPages.length)
pageSelected = pageSelected + 1;
}
const handleDecPage = () => {
if(pageSelected -1 > -1)
pageSelected = pageSelected - 1;
}
</script>
<form bind:this={formNode}>
<FormPage pageData={formPages[pageSelected]} />
</form>
<button on:click={handleDecPage}>Back</button>
<button on:click={handleIncPage}>Next</button>
<p>
Page Selected: {pageSelected}
</p>
А вот компонент FormPage
:
<code>// FormPage.svelte
<script>
export let pageData;
const {name, label} = pageData;
</script>
<div id={`form-page-${name}`}>
<label>Label: {label}</label>
<input type="text" name={name} id={`input-${name}`} />
</div>
<pre>{JSON.stringify(pageData, null, 2)}
Когда я запускаю приложение и inc / dec pageSelected
, pageData
реквизит успешно изменяется - как видно из элемента pre
.Однако элементы label
и input
точно такие же, как на первой странице.id
элемента обтекания div
и id
элемента input
также не изменились.
Когда я набираю input
и меняю страницу, текст остается прежним.
Мои цели: переставить компонент FormPage
, когда pageSelected
изменится, и input
и label
изменят свои значения на основе этих новых реквизитов.Также должно быть так, что когда я меняю страницы, текст, уже введенный в input
, должен обновляться и быть пустым (поскольку начальные значения не задаются для входных данных).
После создания многошаговых формв React.js я использовал бы уникальный атрибут key
, чтобы убедиться, что мои FormPage
перерисовываются каждый раз, когда изменяется состояние pageSelected
.Но я не уверен, как сделать что-то подобное в Svelte.js.
Есть предложения?
ОБНОВЛЕНИЕ:
Прочитав это На вопросе о StackOverflow я узнал, как заставить изменяться элементы input
и label
, а также атрибуты id
.Вот мой обновленный FormPage
компонент:
<code>// FormPage.svelte
<script>
export let pageData;
$: name = pageData.name;
$: label = pageData.label;
</script>
<div id={`form-page-${name}`}>
<label>Label: {label}</label>
<input type="text" name={name} id={`input-${name}`} />
</div>
<pre>{JSON.stringify(pageData, null, 2)}
Однако текст внутри input
по-прежнему не изменяется.
Есть ли способ такжеобновить значение ввода, а?В моем случае было бы идеально создавать абсолютно новый элемент при каждом изменении реквизита, но похоже, что Svelte обновляет только несколько атрибутов, которые изменились на одном и том же базовом узле DOM.
Может ли Svelte бытьвелели воссоздать элементы в этих обстоятельствах?
ОБНОВЛЕНИЕ 2
Итак, я нашел способ получить значение входного значения для изменения.Вот мой обновленный FormPage
компонент:
<code>// FormPage.svelte
<script>
export let pageData;
import {onMount, afterUpdate, onDestroy} from "svelte";
let inputNode;
$: name = pageData.name;
$: label = pageData.label;
$: value = pageData.initialValue || "";
onMount(() => {
console.log("Mounted");
});
afterUpdate(() => {
console.log("Updated");
inputNode.value = value
});
onDestroy(() => {
console.log("Destroyed");
});
</script>
<div id={`form-page-${name}`}>
<label>Label: {label}</label>
<input type="text" name={name} id={`input-${name}`} bind:this={inputNode} />
</div>
<pre>{JSON.stringify(pageData, null, 2)}
Это решает непосредственную проблему обновления входного значения.
Я добавил onMount
,Функции afterUpdate
и onDestroy
позволяют увидеть, как компонент изменяется с течением времени.
Сначала вызывается функция onDestroy
, а затем onMount
.Оба они стреляют только один раз.Однако afterUpdate
срабатывает каждый раз, когда меняется реквизит.Это подтверждает мое подозрение, что компонент не был воссоздан.