iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0
Modern Web

Svelte 的奇妙冒險系列 第 7

[Svelte 的奇妙冒險] Day 07 - 常用的 directives

  • 分享至 

  • xImage
  •  

在 Svelte 中我們能夠利用 directives 去控制元素各種屬性

bind:property

基本上 bind:property 就是在實現雙向綁定,也就是我讓某個元素的 property 與某個 $state 進行綁定讓那個 property 更新時可以更新 $state 反之 $state 更新時也會去讓那個元素的 property 更新。

bind:value

第一個直覺想到適合 bind 的 property 就是 value

<script lang="ts">
	let value = $state('Hello, World!');
</script>

<label>
  <!-- bind:value 是 bind:value={value} 的縮寫 -->
	<input bind:value />
	{value}
</label>

<style>
	label {
		display: flex;
		gap: 0.5em;
	}
</style>

當我們使用了 bind:value 會發現我們不用特地去寫 onchange 之類的 event handler 就能改變 value 也就是使用了 bind 就直接實現了 input$state 的雙向綁定。

對於 select 也是一樣的道理:

<script lang="ts">
	let selected = $state('a');
</script>


<label>
	<select bind:value={selected}>
		<option value={'a'}>a</option>
		<option value={'b'}>b</option>
		<option value={'c'}>c</option>
	</select>
	{selected}
</label>

bind:group

Svelte 提供了 bind:group 這一個相當好用的 directives ,簡單來說它可以讓我們更簡單使用一群 input ,像是 radio button 或者 checkbox 這元件。

在 React 中可能你會需要先寫一個 event handler function 去根據 event.target.valuesetState ,接下來將這個 function 傳入每個 input ,最後將每個 input 的 checked 使用 state 來判斷是不是自己被選了。

但在 Svelte 只要這樣就好:

<script lang="ts">
	let tortilla = $state('Plain');
	let fillingsCheckbox = $state([]);
</script>

<label>
	<input type="radio" bind:group={tortilla} value="Plain" />
	Plain
</label>
<label>
	<input type="radio" bind:group={tortilla} value="Whole wheat" />
	Whole wheat
</label>
<label>
	<input type="radio" bind:group={tortilla} value="Spinach" />
	Spinach
</label>
<p>{tortilla}</p>

<br />

<label>
	<input type="checkbox" bind:group={fillingsCheckbox} value="Rice" />
	Rice
</label>
<label>
	<input type="checkbox" bind:group={fillingsCheckbox} value="Beans" />
	Beans
</label>
<label>
	<input type="checkbox" bind:group={fillingsCheckbox} value="Cheese" />
	Cheese
</label>
<label>
	<input type="checkbox" bind:group={fillingsCheckbox} value="Guac (extra)" />
	Guac (extra)
</label>
<p>
	{fillingsCheckbox.join(', ')}
</p>

只要使用 bind:group 了,元素自己會根據 binding 的 $state 來判斷自己是否被選擇以及實現點擊後更新的行為。

bind:this

就是讓我們能夠獲得 DOM node 。

<script lang="ts">
	import { onMount } from 'svelte';
	
	let canvasElement = $state(0);
	
	onMount(() => {
		const ctx = canvasElement.getContext('2d');
		ctx.fillStyle = 'red';
		ctx.fillRect(10, 10, 100, 100);
	});
</script>

<canvas bind:this={canvasElement} />

class:name

簡單來說就是讓我們能夠簡單的做到 css class 動態切換的 directives ,也就是當它傳入的 state 是 true 時, element 就會擁有那個 class

<script lang="ts">
	let isActive = $state(true);
	let isAdmin = $state(true);
</script>

<button onclick={() => (isActive = !isActive)}>Toggle</button>


<!-- 這兩個是一樣意思 -->
<div class={isActive ? 'active' : ''}>Lorem ipsum dolor sit amet, consectetur adipiscing elit</div>
<div class:active={isActive}>Lorem ipsum dolor sit amet, consectetur adipiscing elit</div>

<!-- 如果 class 剛好叫做 active 可以這麼簡寫-->
<div class:isActive>Lorem ipsum dolor sit amet, consectetur adipiscing elit</div>

<!-- Multiple class toggles can be included -->
<div class:isActive class:inactive={!isActive} class:isAdmin>
	Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>

<style>
	.active {
		color: green;
	}

	.inactive {
		color: red;
	}

	.isAdmin {
		font-weight: bold;
	}
</style>

use:action

就是一個有特定格式的 function ,方便我們可以 reuse 某些 DOM 的操作,會在 onMount 階段時執行 action 裡面操作,然後 onDestroy 會執行 destroy(){}

我們這邊就寫一個元素掛載完後會自動執行動畫的 action

Svelte 有提供更簡單的動畫寫法,但這邊只是為了簡單示範 action 的用法就是了。

<script lang="ts">
	let show = $state(false);

	function greet(element: HTMLElement, duration = 500) {
		element.animate([{ opacity: 0 }, { opacity: 1 }], {
			duration: 500,
			fill: 'forwards'
		});

		return {
			destroy() {
				console.log('destroy');
			}
		};
	}
</script>

<input bind:checked={show} type="checkbox" />

{#if show}
	<div use:greet={100}>Action</div>
	<div use:greet={300}>Action</div>
	<div use:greet>Action</div>
	<div use:greet={1000}>Action</div>
{/if} 

action 的第一個參數都會是 DOM node ,也就是要操作的元素,如果兩個參數要使用時只要記得 DOM node 不用手動自己傳,所以當我們使用了 use:greet={100} 也就代表 duration 被傳入 100

如果兩個參數不敷使用的話,請使用 object 作為參數。


參考資料

source code


上一篇
[Svelte 的奇妙冒險] Day 06 - 深入 $effect
下一篇
[Svelte 的奇妙冒險] Day 08 - 如何寫一個 Component
系列文
Svelte 的奇妙冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言