「我想說你可能會在這邊。」她漫不經心的回應了我的招呼。「我記得你說你就住在這附近。」
接著,作為一個她會再回頭來找我的暗示,她輕輕巧巧的透過 Property 將資料傳給了我,然後就繼續轉頭朝兩位穿著黃色成對洋裝的女孩打招呼去了。~節錄自《The Great Svelte:第三章》
經過了這幾天的研究,現在我們已經對 Svelte 元件當中變數的改變如何帶動 HTML 的更新,以及同時更新其他相關的狀態與陳述句等略知一二了。那麼下一步想要問的,就是不同的 Svelte 元件之間應該要如何傳遞需要的變數呢?
通常在建立一個 Svelte 專案的時候,會把有獨立運作邏輯的區塊拆成幾個不同的 Svelte 元件,這樣個別管理起來比較方便,也能更清楚的撰寫負責不同功能的程式碼。獨立歸獨立,但總有些時候,這些不同的 Svelte 元件會需要共用同一個狀態。將共同需要用到的狀態,在不同 Svelte 元件之間傳遞,就變成一個相當重要的工作。而 Svelte 是藉由怎麼樣的設計來達成這個任務的呢?答案是元件的 Property。
Svelte 元件的 Property 的概念,就跟 HTML 元素的屬性 (attribute) 相當類似。首先,這是一個存在於 Svelte 父元件 (parent component) 當中簡單的 Svelte 子元件 (child component),
<!-- 在一個 Svelte 父元件裡頭使用一個 Svelte 子元件 -->
<ChildComponent />
要將 Javascript 變數的值,傳進這個子元件當中,就像在寫 HTML 元素的屬性:
<!-- 在一個 Svelte 父元件裡頭使用一個子元件,並傳入變數 -->
<ChildComponent someProp={someVariable} />
這邊稍微說明一下,someProp
是屬於子元件 (child component) 的 Property,而 someVariable
則是屬於父元件 (parent component) 當中的 Javascript 變數。
接著,在子元件的程式碼裡頭,我們需要加入這麼一段話,用來接收傳進來的 Property:
<script>
export let someProp;
</script>
如此一來就大功告成。屬於父元件 (parent component) 的 Javascript 變數的值,也就是 someVariable
的值,就會透過 someProp={someVariable}
這一段程式碼,傳達給子元件 (child component)。而子元件 (child component) 一端,則會透過 export let someProp
來接收並使用這個變數的值。
是不是很簡單很方便的設計呢,那就讓我們回到自己的專案當中實際來使用看看。首先找到 App.svelte
:
/src/App.svelte
<!-- 在 Javascript 當中 import Counter -->
<script>
import Counter from './lib/Counter.svelte';
let countOfApp = 1;
let someState = 'TheGreatSvelte';
const sparkle = (text) => {
const sparkles = ['★', '☆', '✧', '✪'];
const randomSparkles = () => sparkles[Math.floor(Math.random() * sparkles.length)];
const sparkledText = text.split('').reduce((a, c) => a + randomSparkles() + c, '');
return sparkledText;
}
const href = 'https://ithelp.ithome.com.tw/users/20120178/ironman/7031';
</script>
<main>
<!-- 在 HTML 當中直接嵌入 Counter,並傳入變數 -->
<Counter countOfCounter={countOfApp}/>
<p class='comment'>Check out <a {href}>Svelte Tutorial</a>, the awesome article powered by {sparkle(someState)}!</p>
</main>
在 App.svelte
當中,還放著我們在第 05 天當中做出來的程式碼。那一段程式碼並不是今天的重點。今天我們只看第三行、第五行、跟第二十行。
第三行:import Counter from './lib/Counter.svelte';
引入我們需要用到的元件 Counter.svelte
。
第五行:let countOfApp = 1;
宣告一個變數 countOfApp
。這個變數是屬於 App.svelte
的。
第二十行:<Counter countOfCounter={countOfApp} />
在 HTML 段落當中,放進我們需要使用 <Counter />
的地方,並利用 countOfCounter={countOfApp}
將 countOfApp
的值傳入 <Counter />
這個元件的 Property countOfCounter
當中。
而另一方面,Counter.svelte
也要寫一段相對應的程式碼,也就是替 Counter.svelte
做出一個可以接收來自父元件 (parent component) 的資料的 Property countOfCounter
:
/src/lib/Counter.svelte
<script>
export let countOfCounter;
</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>{countOfCounter}</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>
第二行:export let countOfCounter;
宣告一個變數 countOfCounter
,並且用關鍵字 export
讓這個變數成為 Svelte 元件的 Property。
第十五行:<p>{countOfCounter}</p>
將 countOfCounter
的值顯示在 HTML 段落中。
圖一、從父元件 (parent component) 拿到資料的子元件 (child component)
有趣的是,Svelte 元件的 Proterty,不僅看起來像 HTML 元素的屬性 (attribute),用起來像 HTML 元素的屬性 (attribute),連連程式碼縮寫的方式都很像。也就是說,當父元件 (parent component) 的變數名稱,跟要傳入子元件 (child component) 的 Property名稱相同時:
<ChildComponent someProp={someProp} />
可以簡單寫成:
<ChildComponent {someProp} />
打鐵趁熱,就讓我們再討論一個與 Svelte 元件 Property 相關的話題:預設值。我們可以幫 Svelte 元件的 Property 做一個預設值。顧名思義,當父元件 (parent component) 在使用子元件 (child component),卻沒有傳入任何變數給子元件 (child component) 相對應的 Property 時,子元件 (child component) 的 Property 就會採用我們先設定好的預設值。
做法簡單也很好理解:
export let someProp = defaultValue;
只要在子元件用關鍵字 export
宣告一個 Property 的同時,賦予一個值,那麼這個值就會是這個 Property 的預設值囉!也讓我們實際來試試看吧:
/src/App.svelte
<!-- 在 Javascript 當中 import Counter -->
<script>
import Counter from './lib/Counter.svelte';
let someState = 'TheGreatSvelte';
const sparkle = (text) => {
const sparkles = ['★', '☆', '✧', '✪'];
const randomSparkles = () => sparkles[Math.floor(Math.random() * sparkles.length)];
const sparkledText = text.split('').reduce((a, c) => a + randomSparkles() + c, '');
return sparkledText;
}
const href = 'https://ithelp.ithome.com.tw/users/20120178/ironman/7031';
</script>
<main>
<!-- 在 HTML 當中直接嵌入 Counter,並傳入變數 -->
<Counter />
<p class='comment'>Check out <a {href}>Svelte Tutorial</a>, the awesome article powered by {sparkle(someState)}!</p>
</main>
<Counter />
countOfCounter={countOfApp}
拿掉,一點資料都不傳給 <Counter />
。
圖二、子元件 (child component) 有 countOfCounter
這個 Property,但是父元件 (parent) 沒有傳資料進來,就變成 undefined
了 😥
趕快幫 Counter.svelte
的 Property 補上預設值。
/src/lib/Counter.svelte
<script>
export let countOfCounter = 100;
</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>{countOfCounter}</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>
export let countOfCounter = 100;
100
。
圖三、100!
那麼今天關於 Svelte 元件的 Property 就介紹到這邊了,謝謝各位讀者的支持。