如何在Svelte中创建自定义事件
#javascript #网络开发人员 #svelte

最近,我正在从事一个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>

您看到我在说什么吗?上面的片段看起来真的很尴尬,如果我们添加了firstNamelastName的另外两个字段,那将是难以忍受的。这是很多需要更新的死亡代码。因此,让我们拆分此代码。

// 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属性中,然后可以使用它。

我刚刚遇到了这个问题,并想到了分享我想出的这个解决方案。我希望您发现这有用,请留下您对我们解决此问题的方法的想法,也告诉我们您是否以不同的方式处理了这种情况。