我是真的有被標註的。一個星期六早上,一位穿著 Svelte 官方橘的司機走進了我庭院的草坪,替他的主人捎來一封十分正式的信息:在每個變數改變的時刻,若我願意跟著重新執行一次陳述句,那將會是他的無上光榮。署名:
$:
。~節錄自《The Great Svelte:第三章》
經過兩天的介紹,我們對 Svelte 當中的 Javascript 是越來越熟悉了,不僅知道 Svelte 是透過賦值 (assign, =
) 來更新變數與呈現的介面,更明白如何透過互動宣告 (reactive declaration, $:
) 來做出衍生自變數的變數。那麼剩下還沒提到的,就是 Svelte 要如何依據變數的變化,去執行 Javascript 的陳述句 (statement) 了。
今天要講的內容,就是 Svelte 的互動陳述 (reactive statement)。如果前一兩天的介紹能讓讀者們對 Svelte 的設計有一些見解,甚至能融會貫通的話,那麼今天要介紹的功能,其實已經說完了。那麼我們不賣關子,直接來看看 Svelte 如何在 Javascript 當中實現互動陳述 (reactive statement) 吧:
let someState;
$: { console.log(someState) };
第一行:let someState;
在 Javascript 當中宣告一個變數 someState
。
第二行:$: { console.log(someState) };
用 $:
當作開頭,接著以大括弧 {}
表示陳述句的段落,裡面可以填入任何想要隨著變數改變而重複執行的陳述句。這邊 console.log()
只是陳述句的一個示範。
看到這裡,是不是想說:怎麼又是 $:
,怎麼又是你,為什麼我不意外。沒錯,這就是 Svelte 慣用的手段。由於 Svelte 編譯器可以追蹤互動陳述 (reactive statement) 當中所使用的變數,當變數發生重新賦值 (assign, =
) 的動作,就透過 $:
來執行相關的陳述句。非常簡單,非常直覺,卻非常有效。
當 Svelte 的互動陳述 (reactive statement) 只有一句陳述句時,用來表達陳述句段落的大括弧 {}
可以省去不寫,也就是說上面示範的互動陳述可以簡寫為:
let someState;
$: console.log(someState);
好的,既然明白陳述句的用法,我們打鐵趁熱,試著在專案當中練習看看。一樣是來到 Counter.svelte
當中:
<script>
let countArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$: count = countArray.length;
const intervalId = setInterval(() => {
countArray = countArray.slice(1);
}, 1000);
$: console.log(count);
$: if (!count) {
clearInterval(intervalId);
console.log('clear interval!');
};
</script>
<section>
<h1>Create Color Palette for Me!</h1>
<div class='counter'>
<button>
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5" />
</svg>
</button>
<div class="counter-viewer">
<p>{count}</p>
</div>
<button>
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
</svg>
</button>
</div>
</section>
第二行:let countArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
宣告一個變數 countArray
。
第三行:$: count = countArray.length;
用 $:
宣告一個衍生自 countArray
的變數。
第六行:countArray = countArray.slice(1);
利用 slice(1)
將 countArray
陣列當中第一個元素給丟掉。要讓 Svelte 認知到 countArray
內容發生改變,我們必須要用賦值的方式,所以這邊不是使用原地 (in-place) 改變陣列資料的函式 shift()
而是 slice()
。若還是想要用 shift()
,可以寫成這樣:
countArray.shift();
countArray = countArray;
第九行:$: console.log(count);
利用 $:
寫一個互動陳述句 (reactive statement)。陳述句內容的變數有 count
,因此只要 count
發生改變,就會重新執行一次這個陳述句,也就是 console.log(count)
。
第十行:$: if (!count) {
利用 $:
再寫一個互動陳述句 (reactive statement)。陳述句內容的變數也只有 count
。當 count
發生改變,陳述句就會重新被執行一次。也就是重新判斷一次 count
布林值。由於 count
是數字 (源自 $: count = countArray.length
),所以當 count
為零,if
這個條件式就會被執行。
第十一行:clearInterval(intervalId);
清除我們先前設定的 setInterval
。
第十二行:console.log('clear interval!');
清除乾淨囉!
第二十六行:<p>{count}</p>
一樣,我們把 count
的值顯示在 HTML 的 <p>
當中。
來看看今天的成果吧:
圖一、10、9、8、7、6、5、4、3、2、1、0、clear interval!
在這一段程式碼當中,我們用了兩個 $:
給兩段互動陳述句 (reactive statement)。這兩段陳述句都希望能夠在 count
改變時重新執行一次。所以我們也可以只用一個 $:
寫成:
$: {
console.log(count);
if (!count) {
clearInterval(intervalId);
console.log('clear interval!');
}
}
那麼這就是今天關於 Svelte 互動陳述句 (reactive statement) 的介紹了,謝謝大家。