在 Svelte 中我們能夠利用 directives 去控制元素各種屬性
基本上 bind:property
就是在實現雙向綁定,也就是我讓某個元素的 property
與某個 $state
進行綁定讓那個 property
更新時可以更新 $state
反之 $state
更新時也會去讓那個元素的 property
更新。
第一個直覺想到適合 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>
Svelte 提供了 bind:group
這一個相當好用的 directives ,簡單來說它可以讓我們更簡單使用一群 input
,像是 radio button 或者 checkbox 這元件。
在 React 中可能你會需要先寫一個 event handler function 去根據 event.target.value
來 setState
,接下來將這個 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
來判斷自己是否被選擇以及實現點擊後更新的行為。
就是讓我們能夠獲得 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} />
簡單來說就是讓我們能夠簡單的做到 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>
就是一個有特定格式的 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
作為參數。