svelte:如何在我自己的组件中使用事件修饰符

ope*_*sas 8 event-handling svelte

我想开发自己的 Button 组件并能够处理事件修饰符,如下所示:

<MyButton on:click|preventDefault={handler}>Click me</MyButton>
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

Event modifiers other than 'once' can only be used on DOM elementssvelte(invalid-event-modifier)
Run Code Online (Sandbox Code Playgroud)

在 MyButton 中,我可以像这样传递 on:click 事件:

<button on:click|preventDefault>
  <slot />
</button>
Run Code Online (Sandbox Code Playgroud)

但是如果没有 PreventDefault 我将无法使用 MyButton

因此,另一种选择是选择性地传递事件修饰符,执行如下操作:

<MyButton preventDefault on:click={handler}>Click me</MyButton>
Run Code Online (Sandbox Code Playgroud)

然后在 MyButton.svelte 中进行类似的操作(我知道这不起作用)以选择性地应用事件修饰符。

<script>
  export let prevenDefault=false
</script>

<button on:click|{preventDefault ? 'preventDefault' : ''}={handler}>Click me</MyButton>
Run Code Online (Sandbox Code Playgroud)

关于如何处理它有什么想法吗?

jas*_*on. 8

我认为有两种方法比较适用:

  1. 防止事件回调中的默认设置(更简单的方法)
  2. 通过传入 prop 来防止默认(您的建议)

防止事件回调中出现默认情况

优点 缺点
实施起来更容易、更干净 该组件的使用者必须Event#preventDefault强制调用

为了进行设置,您需要做两件事。

  1. <Button>要转发其事件的组件:
<script>
  // Button.svelte
</script>

<!-- Note that we're not providing any callback, which forwards it -->
<button on:click>
  <slot />
</button>
Run Code Online (Sandbox Code Playgroud)
  1. 要调用Event#preventDefault事件的父组件:
<script>
  // App.svelte

  import Button from './Button.svelte';
</script>

<Button
  on:click={(event) => {
    event.preventDefault();

    // your code here
  }}
>
  Click Me!
</Button>
Run Code Online (Sandbox Code Playgroud)

通过传入 prop 来防止默认

优点 缺点
声明式添加事件修饰符 组件的使用者将从Event中解开原始对象CustomEvent#detail

这里你还需要两件事。

  1. 在标签<Button>中手动添加回调的组件<script>
<script>
  // Button.svelte

  import {
    onMount,
    onDestroy,
    createEventDispatcher,
  } from 'svelte';

  export let preventDefault = false;

  let button;
  const dispatch = createEventDispatcher();

  onMount(() => {
    button.addEventListener('click', onClick);
  });

  onDestroy(() => {
    button.removeEventListener('click', onClick);
  });

  function onClick(event) {
    if (preventDefault) event.preventDefault();

    dispatch('click', event);
  }
</script>

<button bind:this={button}>
  <slot />
</button>
Run Code Online (Sandbox Code Playgroud)
  1. 父组件传入preventDefaultprop
<script>
  // App.svelte

  import Button from './Button.svelte';
</script>

<Button
  preventDefault
  on:click={({ detail: event }) => {
    // your code here
  })
>
  Click me!
</Button>
Run Code Online (Sandbox Code Playgroud)