最近,我正在从事一个Svelte项目。我有一个形式的组件,我观察到我正在重复大量代码,每个新输入添加到表单中。我意识到自己的演奏无法跟上这一点,因为将来这将是一场噩梦。我还在使用tailwindcss,上了很多课,您已经遇到了一团糟。好的,所以我对如何面对这种情况有一个想法。如果我创建了可以在表单内重复使用的通用输入元素怎么办?为了简单起见,表单和输入将非常基本。这是我们在分开之前的样本。
// form.svelte
<form>
<div>
<label
class="font-semibold text-sm text-gray-600 pb-1 block"
>Email</label>
<input
type="email"
class="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
/>
</div>
<div>
<label
class="font-semibold text-sm text-gray-600 pb-1 block"
>Password</label>
<input
type="password"
class="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
/>
</div>
</form>
您看到我在说什么吗?上面的片段看起来真的很尴尬,如果我们添加了firstName
和lastName
的另外两个字段,那将是难以忍受的。这是很多需要更新的死亡代码。因此,让我们拆分此代码。
// input.svelte
<script>
export let label, type;
</script>
<div>
<label
class="font-semibold text-sm text-gray-600
pb-1 block"
>{label}</label>
<input
{type}
class="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
/>
</div>
现在,我们的表格看起来会好一些,但是我们还没有完成。
// form.svelte
<script>
import Input from './Input.svelte';
const inputs = ['email', 'password'];
</script>
<form>
{#each inputs as input}
<Input
type={input}
label={input.toUpperCase()}
/>
{/each}
</form>
现在,我们需要将用户输入表单的数据绑定到我们可以在JavaScript中使用的值,但是略有挑战提出了自己,因为我们无法使用Svelte的内置bind:value
指令。我们的数据状态不会更新,所以我们该怎么办?
我们需要在输入元素上创建自定义事件。每当元素上有输入事件时,自定义事件就会发出。 Svelte提供了on:input
事件,当输入值的状态更改时,该事件会触发。我们可以将听众附加到此事件中,并且每次被称为自定义事件。让我们来看看摘要。
// input.svelte
<script>
export let label, type;
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher()
</script>
<div>
<label
for={label.toLowerCase()}
class="font-semibold text-sm text-gray-600 pb-1 block"
>{label}</label>
<input
{type}
on:input={(e) => {dispatch('input', e.target.value)}}
id={label.toLowerCase()}
class="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
/>
</div>
我们从Svelte导入createEventDispatcher
,这将使我们能够为此组件创建一个调度程序。我们创建一个可变dispatch
,等于调用createEventDispatcher
的结果。然后,我们在组件上的输入事件附加一个侦听器。因此,每当用户在输入字段中输入一个值时,我们都会使用dispatch
函数派遣自己的自定义input
事件。此函数接受两个参数,第一个是一个字符串,代表我们要派遣的事件。第二个参数是我们希望将任何数据转发给事件附带的听众。现在我们需要从父组件中处理此事件。
// forms.svelte
<script>
import Input from './Input.svelte';
const inputs = ['email', 'password'];
$:user = {
email: '',
password: ''
}
</script>
<form
class="bg-white shadow w-full rounded-lg divide-y divide-gray-200"
>
{#each inputs as input}
<div class="px-5 py-7">
<Input
type={input}
label={input.toUpperCase()}
on:input={(e) => user[input] = e.detail}
/>
</div>
{/each}
在父组件上,这是我们将Input
组件导入的形式。现在,我们聆听input
事件,请记住,Input
组件随时在用户在表单字段中以数据字段中的任何值作为数据键入input
事件。可以从事件对象捕获此数据,它位于事件对象上的detail
属性中,然后可以使用它。
我刚刚遇到了这个问题,并想到了分享我想出的这个解决方案。我希望您发现这有用,请留下您对我们解决此问题的方法的想法,也告诉我们您是否以不同的方式处理了这种情况。