(12)svelte 教程:Dispatching Custom Events
什么是 Dispatching Custom Events
在 Svelte 框架中,Dispatching Custom Events 是指组件可以触发自定义事件,这些事件可以由父组件或其他监听者来捕获和处理。这种机制允许组件之间进行更灵活的通信,不仅限于属性传递,还可以通过事件来传递信息和触发操作。通过这种方式,可以在组件中触发并处理特定的交互行为,提升组件的可复用性和模块化。
逐行解释代码
App.svelte
<script>
import Modal from './Modal.svelte';
import AddPersonForm from './AddPersonForm.svelte';
let showModal = false;
let toggleModal = () => {
showModal = !showModal;
};
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);
};
const addPerson = (e) => {
//console.log(e.detail);
const person = e.detail;
people = [person, ...people];
showModal = false;
};
</script>
-
import Modal from './Modal.svelte';- 从当前目录中导入名为
Modal的 Svelte 组件。
- 从当前目录中导入名为
-
import AddPersonForm from './AddPersonForm.svelte';- 从当前目录中导入名为
AddPersonForm的 Svelte 组件。
- 从当前目录中导入名为
-
let showModal = false;- 声明一个名为
showModal的变量,初始值为false。这个变量用于控制Modal组件的显示与隐藏。
- 声明一个名为
-
let toggleModal = () => { showModal = !showModal; };- 声明一个名为
toggleModal的箭头函数。这个函数的作用是切换showModal的值,使其在true和false之间切换。
- 声明一个名为
-
let people = [ /* ... */ ];- 声明一个名为
people的数组,存储一组人物对象,每个对象包含name、beltColour、age和id属性。注释掉的部分是示例数据。
- 声明一个名为
-
const handleClick = (e, id) => { /* ... */ };- 声明一个名为
handleClick的箭头函数,当点击删除按钮时调用此函数,过滤掉数组中对应id的人物,并输出事件对象e。
- 声明一个名为
-
const addPerson = (e) => { /* ... */ };- 声明一个名为
addPerson的箭头函数,当触发addPerson事件时调用此函数,向people数组添加新人物,并隐藏模态框。
- 声明一个名为
<Modal {showModal} on:click={toggleModal}>
<AddPersonForm on:addPerson={addPerson} />
</Modal>
-
<Modal {showModal} on:click={toggleModal}>- 使用
Modal组件,并传递两个属性:-
{showModal}:将showModal变量的当前值传递给Modal组件,使其能够根据该值决定是否显示。 -
on:click={toggleModal}:监听Modal组件的click事件,当该事件触发时,调用toggleModal函数。
-
- 使用
-
<AddPersonForm on:addPerson={addPerson} />- 在
Modal组件中使用AddPersonForm组件,并监听addPerson事件。当该事件触发时,调用addPerson函数。
- 在
<main>
<button on:click={toggleModal}>Open Modal</button>
{#each people as person (person.id)}
<div>
<h4>{person.name}</h4>
{#if person.beltColour === 'black'}
<p><strong>MASTER NINJA</strong></p>
{/if}
<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>和<button on:click={toggleModal}>Open Modal</button>- 创建一个
main元素,并在其内部创建一个按钮。 -
on:click={toggleModal}:为按钮绑定click事件,当按钮被点击时,调用toggleModal函数,切换showModal的值,从而控制Modal的显示与隐藏。
- 创建一个
-
{#each people as person (person.id)}- 使用
each模板语句遍历people数组,渲染每个人物的详细信息。-
key: person.id:为每个person元素设置唯一键值id,以提高渲染性能。
-
- 使用
-
<div> /* ... */ </div>- 为每个人物创建一个包含其详细信息的
div容器。-
<h4>{person.name}</h4>:显示人物的名字。 -
{#if person.beltColour === 'black'}:如果人物的腰带颜色是黑色,显示 “MASTER NINJA” 标识。 -
<p>{person.age} years old, {person.beltColour} belt.</p>:显示人物的年龄和腰带颜色。 -
<button on:click={(e) => handleClick(e, person.id)}>delete</button>:创建一个删除按钮,绑定点击事件,调用handleClick函数并传递事件对象和人物的id。
-
- 为每个人物创建一个包含其详细信息的
-
{:else} <p>There are no people to show...</p> {/each}- 如果
people数组为空,则显示提示信息 “There are no people to show…”.
- 如果
AddPersonForm.svelte
<script>
import { createEventDispatcher } from 'svelte';
let name;
let beltColour;
let age;
let skills = [];
const dispatch = createEventDispatcher();
const handleSubmit = () => {
const person = {
name,
beltColour,
age,
skills,
id: Math.random()
};
dispatch('addPerson', person);
};
</script>
-
import { createEventDispatcher } from 'svelte';- 从 Svelte 导入
createEventDispatcher函数,用于创建事件调度器。
- 从 Svelte 导入
-
let name;- 声明一个名为
name的变量,用于存储用户输入的名字。
- 声明一个名为
-
let beltColour;- 声明一个名为
beltColour的变量,用于存储用户选择的腰带颜色。
- 声明一个名为
-
let age;- 声明一个名为
age的变量,用于存储用户输入的年龄。
- 声明一个名为
-
let skills = [];- 声明一个名为
skills的数组,用于存储用户选择的技能。
- 声明一个名为
-
const dispatch = createEventDispatcher();- 创建一个事件调度器
dispatch,用于触发自定义事件。
- 创建一个事件调度器
-
const handleSubmit = () => { /* ... */ };- 声明一个名为
handleSubmit的箭头函数,当表单提交时调用此函数,创建一个包含名字、腰带颜色、年龄、技能和唯一id的人物对象,并触发名为addPerson的自定义事件,将人物对象作为事件数据传递出去。
- 声明一个名为
<form on:submit|preventDefault={handleSubmit}>
<input type="text" placeholder='name' bind:value={name}>
<input type="number" placeholder='age' bind:value={age}>
<label>Skills:</label>
<input type="checkbox" bind:group={skills} value="fighting">fighting<br>
<input type="checkbox" bind:group={skills} value="sneaking">sneaking<br>
<input type="checkbox" bind:group={skills} value="running">running<br>
<label>Belt colour:</label>
<select bind:value={beltColour}>
<option value="black">black</option>
<option value="orange">orange</option>
<option value="brown">brown</option>
<option value="white">white</option>
</select>
<button>Add Ninja</button>
</form>
-
<form on:submit|preventDefault={handleSubmit}>- 创建一个表单元素,并绑定
submit事件。当表单提交时调用handleSubmit函数,并通过preventDefault修饰符阻止默认的表单提交行为(即页面刷新)。
- 创建一个表单元素,并绑定
<input type="text" placeholder='name' bind:value={name}>
- 创建一个文本输入框,用于输入名字。通过
bind:value双向绑定,将用户输入的值赋给name变量。
<input type="number" placeholder='age' bind:value={age}>
- 创建一个数字输入框,用于输入年龄。通过
bind:value双向绑定,将用户输入的值赋给age变量。
<label>Skills:</label>
- 创建一个标签,用于描述下面的技能选项。
<input type="checkbox" bind:group={skills} value="fighting">fighting<br>
<input type="checkbox" bind:group={skills} value="sneaking">sneaking<br>
<input type="checkbox" bind:group={skills} value="running">running<br>
- 创建三个复选框,用于选择技能。通过
bind:group将复选框的值绑定到skills数组中。选择或取消选择复选框会将对应的技能添加到或从skills数组中移除。
<label>Belt colour:</label>
- 创建一个标签,用于描述下面的腰带颜色选项。
<select bind:value={beltColour}>
<option value="black">black</option>
<option value="orange">orange</option>
<option value="brown">brown</option>
<option value="white">white</option>
</select>
- 创建一个选择框,用于选择腰带颜色。通过
bind:value将选择框的值绑定到beltColour变量。-
<option value="black">black</option>:创建一个选项,值为 “black”,显示为 “black”。 -
<option value="orange">orange</option>:创建一个选项,值为 “orange”,显示为 “orange”。 -
<option value="brown">brown</option>:创建一个选项,值为 “brown”,显示为 “brown”。 -
<option value="white">white</option>:创建一个选项,值为 “white”,显示为 “white”。
-
<button>Add Ninja</button>
- 创建一个提交按钮,标签为 “Add Ninja”。点击此按钮会触发表单的
submit事件,从而调用handleSubmit函数。
总结
通过以上代码示例,可以看到在 Svelte 中如何创建和触发自定义事件,从而实现组件之间的通信和数据传递。在 AddPersonForm.svelte 中,我们创建了一个事件调度器 dispatch,并在表单提交时触发名为 addPerson 的自定义事件,将新添加的人物数据传递给父组件 App.svelte。在 App.svelte 中,我们通过监听 addPerson 事件来处理新人物的添加操作,并动态更新 people 数组,从而实现页面的动态渲染和更新。
App.svelte 完整代码
<script>
import Modal from './Modal.svelte';
import AddPersonForm from './AddPersonForm.svelte';
let showModal = false;
let toggleModal = () => {
showModal = !showModal;
};
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);
};
const addPerson = (e) => {
//console.log(e.detail);
const person = e.detail;
people = [person, ...people];
showModal = false;
};
</script>
<Modal {showModal} on:click={toggleModal}>
<AddPersonForm on:addPerson={addPerson} />
</Modal>
<main>
<button on:click={toggleModal}>Open Modal</button>
{#each people as person (person.id)}
<div>
<h4>{person.name}</h4>
{#if person.beltColour === 'black'}
<p><strong>MASTER NINJA</strong></p>
{/if}
<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>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
Modal.svelte 完整代码
<script>
export let showModal = false;
export let isPromo = false;
</script>
{#if showModal}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="backdrop" class:promo={isPromo} on:click|self>
<div class="modal">
<slot></slot>
</div>
</div>
{/if}
<style>
.backdrop{
width: 100%;
height: 100%;
position: fixed;
background: rgba(0,0,0,0.8);
}
.modal{
padding: 10px;
border-radius: 10px;
max-width: 400px;
margin: 10% auto;;
text-align: center;
background: white;
}
.promo .modal{
background: crimson;
color: white;
}
</style>
AddPersonForm.svelte 完整代码
<script>
import { createEventDispatcher } from 'svelte';
let dispatch = createEventDispatcher();
let name;
let beltColour;
let age;
let skills = [];
const handleSubmit = () => {
const person = {
name,
beltColour,
age,
skills,
id: Math.random()
}
dispatch('addPerson', person);
};
</script>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" placeholder='name' bind:value={name}>
<input type="number" placeholder='age' bind:value={age}>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label>Skills:</label>
<!-- <input type="checkbox" bind:checked={fighting}>fighting<br>
<input type="checkbox" bind:checked={sneaking}>sneaking<br>
<input type="checkbox" bind:checked={running}>running<br> -->
<input type="checkbox" bind:group={skills} value="fighting">fighting<br>
<input type="checkbox" bind:group={skills} value="sneaking">sneaking<br>
<input type="checkbox" bind:group={skills} value="running">running<br>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label>Belt colour:</label>
<select bind:value={beltColour}>
<option value="black">black</option>
<option value="orange">orange</option>
<option value="brown">brown</option>
<option value="white">white</option>
</select>
<button>Add Ninja</button>
</form>