มาลองหัดเขียน Svelte กันดีกว่า

สวัสดีครับ เนื่องจากว่าผมเพิ่งลองหัดเขียน Svelte ก็เลยนำมาเขียนเป็นบทความสรุปเอาไว้ สำหรับคนที่กำลังเริ่มศึกษา เหมือนๆกันกับผม ซึ่งผมมีพื้นฐาน React.js กับ Vue มา ฉะนั้นบางส่วนอาจจะมีข้ามๆ หรือว่าไม่ได้พูดถึง (ขอติต่างว่ามีพื้นฐาน React หรือ Vue มาก่อนแล้ว) ก็ขออภัยด้วยนะครับ หรือถ้าไม่มีพื้นฐาน Frontend อื่นๆ มาก่อน อย่างน้อย ควรรู้ HTML/CSS/JavaScript พื้นฐานนะครับ
Svelte คืออะไร?
- เป็น Frontend Framework (จริงๆ คือเป็น Compiler) สำหรับทำ UI คล้ายๆ กับ React หรือ Vue
- ปกติ React จะใช้ DOM drifting แต่ตัว Svelte จะอัพเดทเมื่อ state เปลี่ยน
- ดูมีความคล้ายคลึงกับ Vue มากกว่า เช่นมีแบ่ง
<script>
<style>
และ markup / template คล้ายๆ Vue SPC (Single Page Component) - รองรับ Reactivity เหมือนกับ Vue
เริ่มต้นเรียนรู้ Svelte
แน่นอน เว็บของ Svelte มีข้อมูลเริ่มต้นให้เราแล้ว โดยแบ่งเป็น Tutorials, Docs และ Example ครับ
สำหรับใครที่มีพื้นฐาน React / Vue มาก่อน ก็อาจจะเริ่มจาก Getting Started นี้ดู Overview หรือเริ่มจาก Tutorial ไปทีละขั้นก็ได้ครับ - Svelte Overview
พื้นฐาน Svelte
- นามสกุลของไฟล์ จะเป็น
.svelte
เช่นApp.svelte
มองเป็น Component - รูปแบบของไฟล์ svelte จะแบ่งเป็น
<script>
, markup และ<style>
ในไฟล์เดียว
<script> // script</script>
<h1>Hello Svelte!</h1>
<style>h1 { font-size: 5rem;}</style>
- เราสามารถประกาศตัวแปร เพิ่มค่า เหมือน JavaScript ปกติเลย ที่แท็ก
<script>
เช่น
<script>const title = 'Hello Svelte'</script>
- ส่วน markup เราสามารถแสดงค่าตัวแปร ด้วยการใช้
{}
ตัวอย่าง
<h1>{title}</h1>
- สามารถใช้
{}
ร่วมกับ attributes ก็ได้ เช่น<img src="" />
<script> const src = 'https://path/to/image.png' const name = 'short hand'</script>
<img src={src} alt="demo of {name}" />
- เมื่อชื่อ attribute กับตัวแปร เหมือนกัน เราสามารถเขียนแบบย่อได้
<img {src} alt="short hand" />
- เรื่องของ stylesheet ก็เหมือน CSS ปกติเลย เขียนภายใน tag
<style>
และก็ตัว CSS จะมีผลเฉพาะไฟล์นี้ (component scoped) เช่น ถ้าเรากำหนด h1 มีสีแดง ก็จะมีแดงแค่ component นี้ ไม่มีผลกับ component อื่นๆ ตัดปัญหาเรื่อง selector ซ้ำไปได้เลย - การ import Component ก็คล้ายๆ Vue หรือ React คือการ import file ที่เป็น component มา จากนั้นก็ เพิ่มใน markup ตัวอย่างเช่นมี Child.svelte และ Parent.svelte
<script> import Child from './Chlid.svelte'</script>
<Child />
ตัวอย่างข้อมูลในไฟล์ Child.svelte
<h1>This is child component</h1>
Reactivity
feature นี้ตัว Svelte บอกว่าเป็นหัวใจหลักเลย ก็คือมันจะทำหน้าที่คอย sync DOM element กับ application state ของเรา เช่นค่า onclick หรือ user input หรือการเปลี่ยน data ต่างๆ เพื่ออัพเดทข้อมูลอัตโนมัติ (เปลี่ยนค่า DOM)
- ตัวอย่างการ handle onclick ใช้
on:click
directive ซึ่งรูปแบบของมันคือ on:eventname เช่นon:click
,on:mouseenter
หรือon:input
เป็นต้น
<script> let count = 0;
function incrementCount() { count += 1; }</script>
<button on:click={incrementCount}> Clicked {count} {count === 1 ? 'time' : 'times'}</button>
- จากโค๊ดด้านบน เมื่อคลิ๊ก button ค่า count จะเพิ่มทีละ 1 และหน้าเว็บ ก็จะแสดงผลค่า count อัพเดท realtime นั่นเอง
- เราสามารถ sync ค่าจากตัวแปรอื่นๆ ก็ได้ ด้วยการใช้
$:
ตัวอย่างdoubled
จะถูกอัพเดททุกครั้งที่count
มีการเปลี่ยนค่า
<script> let count = 0; $: doubled = count * 2;
function handleClick() { count += 1; }</script>
<button on:click={handleClick}> Clicked {count} {count === 1 ? 'time' : 'times'}</button>
<p>{count} doubled is {doubled}</p>
- reactivity กับพวก array หรือ object ต้องเป็น immutable เท่านั้น จะไม่มีผลกับ mutable data เช่น ไป
array.push()
,pop()
อะไรพวกนั้น
Props
- การกำหนด component properties ทำได้ง่ายๆ ด้วยการ กำหนด ตัวแปรเป็น
export
เช่น มีไฟล์ชื่อHello.svelte
<script>export let title</script>
- เวลาเพิ่มใน markup ก็ส่ง props (attribute) ไปแบบนี้
<Hello title="This is title" />
- กำหนด props เป็น optional ได้ ด้วยการ assign ค่า default value เอาไว้ (ถ้าไม่มี props ส่งมา ก็จะใช้ค่าเริ่มต้น)
<script>export let title = 'default title'</script>
Logic
- Logic การ render เป็น block ผมว่าอ่านง่ายกว่า React (ถ้าเทียบกับมือใหม่ เพราะหลายๆ คนจะงงๆ ternary operator ใน JSX)
- ใช้ block
#if <condition>
ได้เลย แบบนี้
{#if user.loggedIn} <button on:click={logout}> Log out </button>{/if}
- การใช้ if/else จะใช้แบบนี้
{#if user.loggedIn} <button on:click={toggle}> Log out </button>{:else} <button on:click={toggle}> Log in </button>{/if}
- ข้อสังเกต
{#if}
สำหรับเริ่มต้น block{/if}
สำหรับปิด block แต่ถ้ามี ต่อเนื่องใน block จะใช้{:else}
เช่นเดียวกับ{:else if}
- การ loop ข้อมูล จะใช้
{#each expression as name}...{/each}
เช่น
<ul> {#each cats as cat} <li> <a target="_blank" href="https://www.youtube.com/watch?v={cat.id}" rel="noreferrer"> {cat.name} </a> </li> {/each}</ul>
- สามารถใช้ destructuring ได้เช่นกัน
{#each cats as { id, name }}
- list เราควรกำหนด key ให้มันด้วย เพื่อเป็น unique identifier
{#each cats as cat, (cat.id)}
- เราสามารถทำ async data ด้วยการใช้ await block
{#await promise
} ได้ด้วย ลองดูตัวอย่าง https://svelte.dev/examples/await-blocks - การ bind value กับ input (ให้ความรู้สึกเมื่อสมัย AngulasJS ออกมาเลย) เราใช้ syntax
bind:value={variable}
ตัวอย่าง
<script> let name = 'world';</script>
<input bind:value={name}>
<h1>Hello {name}!</h1>
ทั้งหมดนี้ก็เป็นตัวอย่างคร่าวๆ การใช้ Svelte นะครับ ซึ่งผมก็นำมาเขียนเป็นสรุปจากที่อ่าน Tutorial และก็ดู Example คร่าวๆครับ จริงๆ ยังมีอีกหลายเรื่องที่ยังไม่ได้พูดถึง ก็ลองไปศึกษากันดูนะครับ ใครที่มีพื้นฐานจาก Vue/React คิดว่าอ่านแปปๆเดียวก็ทำได้แล้วครับ
สุดท้ายหลังจากลองอ่านแล้ว ลองไปฝึกทำกันดูจริงๆ ด้วยการใช้ SvelteKit ขึ้นโปรเจ็คก็ดีนะครับ แล้วเดี๋ยวบทความหน้าผมจะลองไปหัดใช้ SvelteKit และมาสรุปเป็นบทความไว้เหมือนเดิมครับ ขอบคุณครับ
Happy Coding ❤️
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust