這是〈Svelte 從小白到入門〉系列的第一集,各集連結如下:
- 〈Svelte 從小白到入門(一)元件、事件、Reactivity〉
- 〈Svelte 從小白到入門(二)Props、邏輯、迴圈、Await〉
- 〈Svelte 從小白到入門(三)事件〉
- 〈Svelte 從小白到入門(四)數據綁定〉
- 〈Svelte 從小白到入門(五)生命週期〉
- 〈Svelte 從小白到入門(六)Store〉
- 〈Svelte 從小白到入門(七)動態效果〉
- 〈Svelte 從小白到入門(八)進出場效果〉
- 〈Svelte 從小白到入門(九)動畫效果〉
- 〈Svelte 從小白到入門(十)Action〉
- 〈Svelte 從小白到入門(十一)CSS Class〉
- 〈Svelte 從小白到入門(十二)Slot〉
- 〈Svelte 從小白到入門(十三)Context〉
- 〈Svelte 從小白到入門(十四)Svelte 的特殊元素〉
- 〈Svelte 從小白到入門(十五)Module Context〉
- 〈Svelte 從小白到入門(十六)Debugging〉
- 〈Svelte 從小白到入門(十七)結束與展望〉
Svelte 是年輕且發展迅猛的 JS 框架,與 React / Vue 最大的差異是經過 compile 後的 Svelte 元件是以瀏覽器原生的 DOM 操作,省掉了 virtual DOM 這層轉換的開銷,因此在客戶端上執行的效率更高。
本篇是個人整理的 Svelte 學習筆記,內容與範例主要來自於 Svelte Tutorial,但經過適當的簡化與改寫,希望能縮短一半的篇幅的同時傳達出相當的資訊量。
起手式
在 Svelte 的首頁有放開立空白 Svelte 專案的做法,但在這裡我們並不先開立專案,我們使用 Svelte REPL 做為學習的環境,因此起手式超級簡單,只要用瀏覽器開 Svelte REPL 就立馬有個現成可用的 Svelte 環境,在上面註冊帳號後也可以把自己寫的 Svelte 元件存起來。
Svelte 基礎
「Svelte 元件」是構成 Svelte 專案的基礎,也是我們後續撰寫的主要對象,而 Svelte 元件本身是包含了 HTML、CSS、JS 的 .svelte 檔案。
可以把 .svelte 檔案理解為一種被強殖 Svelte 特性的 .html 檔案,裡面有 HTML 標籤與內容,也有 <script>
區塊放元件的程式邏輯,還有 <style>
區塊放元件的樣式。
元件與元件之間是隔離的,彼此不共享元件內的 JS 及 CSS,即便存在於某兩個元件內的 CSS 具有相同的命名,他們在 compile 後也會被重新命名,讓彼此的參照是獨立的,藉此達到隔離的效果,當然 Svelte 也提供了元件與元件之間傳值的機制,並且元件也可以包含另一個子元件,透過這樣重複包裝的巢狀元件,最終構築出一個完整的 web app。
Hello world
第一個元件是老朋友「Hello world!」,在 <script>
區塊內定義的值 name
,可以直接在 HTML 內以大括號包圍的格式 {name}
呼叫,因為 name
是字串,也可以在大括號內直接調用 name
的字串函式:
HTML 標籤屬性插值
前面我們把 name
做為內容插入,Svelte 也可以讓我們把值做為 HTML 的屬性插入:
當作屬性插入時,要不要用雙引號包住都是可以的,Svelte 會自動識別與轉換(其實在 HTML 的規範內,是允許省略雙引號的)。
範例內的第三種用法較特別,如果 JS 變數名故意取的和 HTML 屬性名一樣,那就可以用這種簡化的格式,讓我們可以少打幾個字。
巢狀元件
如同在 JS 引入其他套件一般,我們用 import
語句在 App.svelte 元件內引入另一個 Nested.svelte 元件,並且以 <Nested>
的形式在 HTML 內調用:
要注意的是,Svlte 的元件都應該要以大寫開頭的形式命名,避免與 HTML 原生標籤混淆。
另外注意到 App.svelte 內的 <p>
被我們改成紫色,並且這並不影響子元件 Nested.svelte 內的 <p>
,這印證了前面說的「元件是互相隔離的」的說法。
內含 HTML 標籤的字串處理
如果 JS 字串內含有 HTML 標籤,基於安全考量,預設的情況下是會被跳脫處理的,也就是會被處理成純文字,如果想要關閉這個特性,那得加上額外的 @html
標示:
該怎麼理解這個 @html
?個人是把它理解為一個裝飾器(decorator),然而這只是個人的解讀,在 Svelte 文件內並沒有明確定義 @html
的角色。
Reactivity
在我以前念的化學領域,reactivity 指的是物質的反應性,而在程式領域,reactivity 的華文是「回應式程式設計」,可以簡單的理解為「JS 與 HTML 的連動機制」。
我們可以透過下面的實例感受所謂的 reactivity,按鈕內的 {count}
是隨著 JS 內的 count
而變的,他們之間的連動特性是由 Svelte 提供的,因此我們再也不用手動處理元件的更新:
在上面的例子中:
- 按鈕與 click 事件是透過
on:click
語句綁定的,這是 Svelte 特有的事件綁定語法,與 HTML 標籤原有的onclick
屬性相當相似,應該很容易理解,只要記得不要打錯字。 - 按鈕內的
{count === 1 ? 'time' : 'times'}
僅是一個決定單字單複數形的三元表達式。(零後面到底要跟單數名詞,還是複數名詞?)
Reactive Declarations
讓上面的例子再複雜一點,放另一個變數 doubled
,並且我們希望這個 doubled
是 count
的兩倍。
我們可以在 HTML 內加入一個簡單的敘述 {count * 2}
得到兩倍的數值,但若是需要重複調用,那就要無數次的 {count * 2}
,這不利於未來的重構,為此我們需要另一個 Svelte 特有的語法,以 $: doubled
的形式賦予這個變數 doubled
也具有 reactivity 的特性:
被加上 $:
修飾後的 doubled
,會在狀態發生變化時,自動重新執行,所謂的狀態發生變化,以上例來說,就是 handleClick()
內 count
的數值改變。
Reactive Statements
$:
不僅能為變數加上 reactivity 的特性,它也能用於其他的程式敘述,讓該句敘述也能因應狀態變化而再次執行。
下面的範例中,每次點擊都會引發 count
改變,並且我們又用 $: console.log(
令這句敘述也會隨著 the count is ${count}
);count
的改變而再次執行:
$:
可以拿來修飾變數、修飾敘述,還可以拿來修飾區塊:
小結
整理一下截至目前為止我們遇到的 Svelte 特有語法:
@html
:讓內含 HTML 標籤的字串不經過跳脫處理,直接原樣送給瀏覽器 render。on:
:綁定 HTML 元素的事件行為。$:
:賦予變數或敘述令其具有 reactivity 的特性。
元件化、資料綁定、事件綁定是每個現代化 web 框架都具有的特性,每個框架實現的方式各異,在這一集我們介紹了 Svelte 在這三方面的用法,多少會有點奇葩之感,然而這些奇葩的語法,未來只會更多,讓我們拭目以待。
(待續)