(5)svelte 教程:Inline Event Handlers(内联事件处理程序)

(5)svelte 教程:Inline Event Handlers(内联事件处理程序)

什么是 Inline Event Handlers

Inline Event Handlers(内联事件处理程序) 是指在 HTML 元素的属性中直接定义事件处理函数。当某个事件(如点击、输入等)发生时,这些处理函数会被调用。在 Svelte 中,内联事件处理程序通过 on: 前缀和内联的箭头函数来绑定事件处理。

逐行解释代码

我们来看一个具体的代码示例,然后逐行详细解释每个部分和参数的含义:

<script>
    let people = [
        { name: 'yoshi', beltColour: 'black', age: 25, id: 1 },
        { name: 'mario', beltColour: 'orange', age: 45, id: 2 },
        { name: 'luigi', beltColour: 'brown', age: 35, id: 3 }
    ];

    const handleClick = (e, id) => {
        people = people.filter(person => person.id != id);
        console.log(e);
    };
</script>
  • let people = [...]

    • 声明一个名为 people 的变量,并将其初始化为一个包含对象的数组。每个对象代表一个人,具有 name(名字)、beltColour(腰带颜色)、age(年龄)和 id(唯一标识符)属性。
  • const handleClick = (e, id) => { ... }

    • 声明一个名为 handleClick 的函数,该函数接收两个参数 eid
    • e:事件对象,包含了事件相关的所有信息。当点击事件触发时,Svelte 会将事件对象传递给 handleClick 函数。
    • id:当前点击的按钮所对应的 person 对象的唯一标识符,用于在数组中识别并删除该对象。
    • people = people.filter(person => person.id != id);:使用 filter 方法创建一个新的 people 数组,过滤掉 id 与传入的 id 不匹配的 person 对象,实现删除功能。
    • console.log(e);:在控制台输出事件对象,用于调试和查看事件的详细信息。
<main>
    {#each people as person (person.id)}
        <div>
            <h4>{person.name}</h4>
            <p>{person.age} years old, {person.beltColour} belt.</p>
            <button on:click={(e) => handleClick(e, person.id)}>delete</button>
        </div>
    {:else}
        <p>There are no people to show...</p>
    {/each}
</main>
部分
  • <main>

    • HTML <main> 元素,用于包裹组件的主要内容。
  • {#each people as person (person.id)}

    • Svelte 的 each 块,用于遍历 people 数组。people 数组中的每个元素(对象)被赋值给 person 变量,并在循环体内使用。
    • (person.id):这是一个键值表达式,用于帮助 Svelte 跟踪每个项的唯一性。通过 person.id,Svelte 可以高效地更新和重排 DOM。
  • <div>

    • HTML <div> 元素,用于包裹每个人的信息。
  • <h4>{person.name}</h4>

    • HTML <h4> 标题元素,使用 {person.name} 表达式将当前 person 对象的 name 属性值插入到标题中。
  • <p>{person.age} years old, {person.beltColour} belt.</p>

    • HTML <p> 段落元素,使用 {person.age}{person.beltColour} 表达式将当前 person 对象的 agebeltColour 属性值插入到段落中。
  • <button on:click={(e) => handleClick(e, person.id)}>delete</button>

    • HTML <button> 按钮元素,使用 on:click 语法为按钮绑定点击事件。
    • (e) => handleClick(e, person.id):内联事件处理程序,定义一个箭头函数,当按钮被点击时,调用 handleClick 函数,并传递事件对象 e 和当前 person 对象的 id
    • handleClick(e, person.id):调用 handleClick 函数,传递事件对象和 personid,从而在 people 数组中删除相应的 person 对象。
  • {:else}

    • each 块的 else 分支,当 people 数组为空或未定义时,显示 else 分支中的内容。
  • <p>There are no people to show...</p>

    • people 数组为空时,显示此段落文本,提示没有人可以显示。
  • {/each}

    • 结束 each 块。

代码总结

这个 Svelte 组件定义了一个 people 数组,并使用 each 块遍历该数组中的每个对象。在每次循环中,它会创建一个包含该对象信息的 <div> 元素,并为每个 <button> 按钮绑定点击事件。点击按钮时,会调用 handleClick 函数,删除相应的 person 对象,并更新 people 数组。如果 people 数组为空,显示一条提示信息。通过这种方式,组件能够动态生成和显示列表内容,并处理用户交互事件。

以下代码有什么区别

<button on:click={(e) => handleClick(e, person.id)}>delete</button>
<button on:click={handleClick(person.id)}>delete</button>

这两种调用方式在事件处理上的主要区别在于它们的执行时机和参数传递方式。让我们逐一解释:

第一种调用方式:箭头函数绑定

<button on:click={(e) => handleClick(e, person.id)}>delete</button>
解释
  • on:click={(e) => handleClick(e, person.id)}:这是使用箭头函数进行事件处理绑定的方式。
  • on:click:表示绑定点击事件。
  • {(e) => handleClick(e, person.id)}:定义一个内联箭头函数。当按钮被点击时,这个箭头函数会被执行,并将事件对象 eperson.id 作为参数传递给 handleClick 函数。
特点
  1. 动态传参:每次点击时,都会生成一个新的箭头函数实例,并动态传递 person.id
  2. 访问事件对象:能够访问事件对象 e,便于在处理函数中使用事件的相关信息。
  3. 执行时机:点击按钮时,箭头函数被执行,从而调用 handleClick 函数。

第二种调用方式:直接绑定函数调用

<button on:click={handleClick(person.id)}>delete</button>
解释
  • on:click={handleClick(person.id)}:这是直接绑定函数调用的方式。
  • on:click:表示绑定点击事件。
  • {handleClick(person.id)}:直接调用 handleClick 函数,并传递 person.id 作为参数。
特点
  1. 立即执行:由于 handleClick(person.id) 是一个函数调用,它会在组件渲染时立即执行,而不是在点击时执行。
  2. 不传递事件对象:无法访问事件对象 e,因为 handleClick 函数在渲染时就已经执行,并且只传递了 person.id
  3. 无效绑定:这种方式实际上不会将 handleClick 绑定为事件处理函数,而是在渲染时执行 handleClick 函数的结果(通常是 undefined),导致绑定无效。

代码示例

为了展示两种调用方式的区别,我们可以修改示例代码如下:

<script>
    let people = [
        { name: 'yoshi', beltColour: 'black', age: 25, id: 1 },
        { name: 'mario', beltColour: 'orange', age: 45, id: 2 },
        { name: 'luigi', beltColour: 'brown', age: 35, id: 3 }
    ];

    const handleClick = (e, id) => {
        people = people.filter(person => person.id != id);
        console.log(e);
    };
</script>

<main>
    {#each people as person (person.id)}
        <div>
            <h4>{person.name}</h4>
            <p>{person.age} years old, {person.beltColour} belt.</p>
            <!-- 使用箭头函数绑定 -->
            <button on:click={(e) => handleClick(e, person.id)}>delete</button>
            <!-- 直接绑定函数调用(注意:这种方式是错误的) -->
            <button on:click={handleClick(person.id)}>delete</button>
        </div>
    {:else}
        <p>There are no people to show...</p>
    {/each}
</main>

总结

  • 使用箭头函数绑定:适用于需要动态传递参数和访问事件对象的情况。在点击时调用处理函数,并传递事件对象和所需参数。
  • 直接绑定函数调用:这种方式实际上在渲染时立即执行函数,并且不适合作为事件处理函数的绑定方式,通常会导致错误。

在实际开发中,应避免直接绑定函数调用的方式,而应使用箭头函数或其他正确的方式绑定事件处理函数,以确保事件处理函数在合适的时机被正确调用。

为什么input 可以不用传入 e参数,而 click 必须要

在 Svelte 中,事件处理函数的行为依赖于事件类型和绑定方式。为了更好地理解为何某些事件处理函数需要事件对象 e,而其他情况则不需要,我们可以深入探讨 on:inputon:click 的不同之处。

输入事件 (on:input)

对于 input 元素的 on:input 事件,Svelte 提供了双向绑定机制,使得处理输入事件变得非常简便。可以通过 bind:value 属性来实现变量与输入框值的自动同步,无需手动处理事件对象 e。如下例所示:

<script>
    let beltColour = "black";
</script>

<main>
    <input type="text" bind:value={beltColour}>
    <p>{beltColour}</p>
</main>

在上述代码中:

  • bind:value={beltColour}:Svelte 的双向绑定语法,使得输入框的值与 beltColour 变量自动同步。无需显式处理事件对象 e

当然,如果你想手动处理 input 事件,可以使用事件对象 e,例如:

<script>
    let beltColour = "black";

    const handleInput = (e) => {
        beltColour = e.target.value;
    };
</script>

<main>
    <input type="text" on:input={handleInput} value={beltColour}>
    <p>{beltColour}</p>
</main>

点击事件 (on:click)

对于 button 元素的 on:click 事件,通常需要处理点击的具体细节,如点击的位置、触发的目标等。因此,传递事件对象 e 是必要的,以便在处理函数中访问这些信息。如下例所示:

<script>
    let people = [
        { name: 'yoshi', beltColour: 'black', age: 25, id: 1 },
        { name: 'mario', beltColour: 'orange', age: 45, id: 2 },
        { name: 'luigi', beltColour: 'brown', age: 35, id: 3 }
    ];

    const handleClick = (e, id) => {
        people = people.filter(person => person.id != id);
        console.log(e); // 处理事件对象
    };
</script>

<main>
    {#each people as person (person.id)}
        <div>
            <h4>{person.name}</h4>
            <p>{person.age} years old, {person.beltColour} belt.</p>
            <button on:click={(e) => handleClick(e, person.id)}>delete</button>
        </div>
    {:else}
        <p>There are no people to show...</p>
    {/each}
</main>

在上述代码中:

  • on:click={(e) => handleClick(e, person.id)}:内联箭头函数传递事件对象 eperson.idhandleClick 函数。
  • handleClick 函数中处理点击事件的具体逻辑,使用事件对象 e 进行日志记录或其他操作。

事件处理函数的差异

  1. 双向绑定(bind:value
  • 输入事件的双向绑定使得变量与输入框值自动同步,无需显式处理事件对象 e
  1. 手动处理事件
  • 对于复杂的点击事件处理,通常需要事件对象 e 以便获取点击的具体细节,并进行相应处理。

总结

  • 输入事件(on:input

    • 使用 bind:value 可以避免手动处理事件对象 e
    • 若需要手动处理输入事件,则使用事件对象 e 获取输入框的值。
  • 点击事件(on:click

    • 通常需要事件对象 e 以便处理点击的具体细节。
    • 通过内联箭头函数传递事件对象 e 和其他参数给处理函数。

了解这些差异有助于选择合适的方式处理不同类型的事件,以便在 Svelte 中更有效地编写响应式和交互式的组件。

APP.svelte 完整代码

<script>
	let people = [
    { name: 'yoshi', beltColour: 'black', age: 25, id: 1 },
    { name: 'mario', beltColour: 'orange', age: 45, id: 2 },
    { name: 'luigi', beltColour: 'brown', age: 35, id: 3 }
  ];

  const handleClick = (e, id) => {
    people = people.filter(person => person.id != id);
    console.log(e);
  };
</script>

<main>
  {#each people as person (person.id)}
    <div>
      <h4>{person.name}</h4>
      <p>{person.age} years old, {person.beltColour} belt.</p>
      <button on:click={(e) => handleClick(e, person.id)}>delete</button>
	  <!-- <button on:click={handleClick(person.id)}>delete</button> -->
    </div>
  {:else}
    <p>There are no people to show...</p>
  {/each}
</main>

<style>
	main {
		text-align: center;
		padding: 1em;
		max-width: 240px;
		margin: 0 auto;
	} 

	h1 {
		color: #ff3e00;
		text-transform: uppercase;
		font-size: 4em;
		font-weight: 100;
	}

	@media (min-width: 640px) {
		main {
			max-width: none;
		}
	}
</style>
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值