Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Svelte - 如何在前端框架中脫穎而出 | ModernWeb'21

Kalan
September 25, 2021
120

Svelte - 如何在前端框架中脫穎而出 | ModernWeb'21

## 內容

- Svelte 簡介
- 探索前端框架的本質
- 介紹一些 Svelte 特有的語法與功能
- 實際使用後的心得分享

This slide is powered by slidev.

https://sli.dev/

Kalan

September 25, 2021
Tweet

Transcript

  1. CodeSandbox pure-js kjj6198 1.2k 0 0 Edit Sandbox Files .codesandbox

    src index.js styles.css index.html package.json Dependencies 9 Console 0 Problems 0 Open Sandbox function render(countdown) { document.getElementById("app").innerHTML = ` <span class="number">${countdown}</span> `; } let countdown = 10; function start() { let timer = setInterval(() => { countdown -= 1; if (countdown === 0) { clearInterval(timer); } render(countdown); }, 1000); } render(10); start(); Svelte - 如何在前端框架中脫穎而出
  2. 其他前端框架如何達成 reactive 如何通知應用狀態已經更新? const Countdown = () => { const

    [countdown, setCountdown] = useState(10); useEffect(() => { setInterval(() => { setCountdown(c => c -= 1); }, 1000) }, []) return <span>{countdown}</span> } <script setup> import { ref, onMounted } from 'vue'; const countdown = ref(10); onMounted(() => { setInterval(() => countdown.value -= 1, 1000); }) </script> <template> <span>{{countdown}}</span> </template> Svelte - 如何在前端框架中脫穎而出
  3. 問題點 必須配合 JavaScript 機制 diff 機制為 runtime 帶來負擔 開發者需自行優化效能 useMemo

    useCallback React.memo … 如果我們可以在其他地方處理變 數追蹤呢? Svelte - 如何在前端框架中脫穎而出
  4. Svelte 如何達到 reactivity Svelte 元件 React CodeSandbox svelte-countdown kjj6198 4.6k

    0 0 Edit Sandbox Files .codesandbox public App.svelte index.js Console 2 Problems 0 Open Sandbox 事先在編譯並生成 JavaScript 程式碼 <script> let countdown = 10; onMount(() => { setInterval(() => countdown -= 1, 1000); }) </script> <span>{countdown}</span> Svelte - 如何在前端框架中脫穎而出
  5. Adam Rackis @AdamRackis omfg 4:23 AM · Sep 16, 2021

    Svelte - 如何在前端框架中脫穎而出
  6. 特色 寫更少的程式碼 沒有虛擬 DOM 機制 響應機制 語法與 HTML JavaScript CSS

    完全相容 事先編譯元件並產生程式碼 簡化後的語法與靜態分析讓程式碼更簡潔 Svelte - 如何在前端框架中脫穎而出
  7. 但…這看起來很 magic CPU 製程算不算 magic? 作業系統算不算 magic? 瀏覽器算不算 magic? JSX/babel/webpack

    算不算 magic? Vue 的 template syntax 算不算 magic? 只要是抽象化,或多或少都具備了「magic」的要素 定義 magic:實作背後有一連串開發者不清楚的運作機制 Svelte - 如何在前端框架中脫穎而出
  8. 變數宣告與 prop <script> import Profile from './Profile.svelte'; 引入其他 Svelte 元件

    let state = false; export let prop = 'hello'; // 加上 export 就變成 prop 了 state = true; // 任何 assignment 都會觸發更新 </script> <Profile user={user} /> Svelte - 如何在前端框架中脫穎而出
  9. 響應式語法 在 countdown 有變化時重新呼叫 format 函數 約等於 react 當中的 useEffect

    約等於 vue 當中的 computed 當某變數改變時做出反應 <script> import { onMount } from 'svelte'; let countdown = 80; $: formatted = `${format(countdown, 'xx:xx')}`; onMount(() => { setInterval(() => countdown -= 1, 1000) }); </script> <span>{formatted}</span> Svelte - 如何在前端框架中脫穎而出
  10. $: 這個語法好奇怪 標籤陳述式(label statement) 很少人在用的 JavaScript 語法 Svelte 會追蹤此區塊內的變數 Vue

    的 ref 語法糖提案當中也參考了此功能 <script> let a = 10; $: { console.log(a); // 每次變數 a 更新時呼叫 console.log(a) } </script> <span>{a}</span> Svelte - 如何在前端框架中脫穎而出
  11. 跨元件狀態管理機制 Svelte 中內建 store 可直接使用 .subscribe .set .update 透過 $

    前綴減少開發者的認知負擔 可在外部 JS 檔案宣告 import { writable } from 'svelte/store'; export const store = writable( { conference: 'modernweb2021' } ) Svelte - 如何在前端框架中脫穎而出
  12. $ 可幫助節省程式碼 在元件掛載時自動訂閱 store 在元件銷毀時解除訂閱 store 效果大約等於: <script> import {

    store } from './store'; $: console.log($store.conference); </script> <h1>Conference: {$store.conference}</h1> <script> import store from './store'; let conference; onMount(() => { const unsubscribe = store.subscribe(store => { conference = store.conference }) return () => unsubscribe() }) </script> <h1>{conference}</h1> Svelte - 如何在前端框架中脫穎而出
  13. 樣板語法 具備響應式特性 容易理解 CodeSandbox age-example kjj6198 582 0 0 Edit

    Sandbox Files .codesandbox public 目前年齡:16 歲 長一歲 未成年 Console 2 Problems 0 Open Sandbox 具有響應式特性的樣板語法 {#if age >= 18} <span> 已成年</span> {:else} <span> 未成年</span> {/if} <script> export let age = 16; const handleClick = () => age++; </script> <button on:click={handleClick}> 長一歲</button> Svelte - 如何在前端框架中脫穎而出
  14. transition 機制 可和 if 語法搭配 不需要額外撰寫 CSS class 動態產生 CSS

    Animation(而非直接操作 style ) CodeSandbox transition-example kjj6198 653 0 0 Edit Sandbox Console 2 Problems 0 Open Sandbox 可透過宣告式的語法建立進出場動畫 <script> import { fade } from 'svelte/transition'; let go; setInterval(() => { go = !go; }, 1000); </script> {#if go} <p in:fade="{ duration: 100 }" out:fade="{ duration: 200 }" >Hello world</p> {/if} Svelte - 如何在前端框架中脫穎而出
  15. crossfade + animate CodeSandbox svelte-animate-example kjj6198 125 0 0 Edit

    Sandbox Files .codesandbox public App.svelte Button.svelte index.js package.json JavaScript React Vue Angular Svelte Selected Console 2 Problems 0 Open Sandbox 計算節點位置並觸發動畫 <script> import { crossfade } from 'svelte/transition'; const [send, receive] = crossfade({ duration: d => Math.sqrt(d * 350), easing: cubicOut, fallback: fade, }) </script> {#each tags as tag (tag.id)} <button animate:flip in:receive={{key: tag.id}} out:send={{key: tag.id}} > {tag.text} </button> {/each} Svelte - 如何在前端框架中脫穎而出
  16. 綁定機制 雙向綁定讓程式碼更加簡潔 <script> let value; let node; let clientWidth; </script>

    <input type="text" bind:value={value} /> <canvas bind:this={node}></canvas> <div bind:clientWidth>{clientWidth}</div> Svelte - 如何在前端框架中脫穎而出
  17. 也可以綁定 <video> 或 <audio> 不需要額外撰寫監聽事件的邏輯 (timeupdate volumechange 等) 改變變數值可以更新 DOM

    屬性(部分唯讀屬 性無法) <script> let duration; let muted = false; let currentTime = 0; let paused = true; let volume = 0.5; if (previousPlayedTime) { currentTime = previousPlayedTime } </script> <audio bind:duration bind:currentTime bind:muted bind:paused bind:volume ... /> Svelte - 如何在前端框架中脫穎而出
  18. 回頭探討:Svelte 解決了哪些問題 用更簡化的語法達到響應式效果 → 減少認知負擔 能在編譯時期做的事情就不在 runtime 做 → 減少

    bundle size 透過描述符(directive)提高程式碼的靈活度 → 減少程式碼撰寫量 Svelte - 如何在前端框架中脫穎而出