iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
Modern Web

了不起的 Svelte系列 第 10

第 10 天:Svelte 元件的 Property

  • 分享至 

  • xImage
  •  

第 10 天:Svelte 元件的 Property

「我想說你可能會在這邊。」她漫不經心的回應了我的招呼。「我記得你說你就住在這附近。」
接著,作為一個她會再回頭來找我的暗示,她輕輕巧巧的透過 Property 將資料傳給了我,然後就繼續轉頭朝兩位穿著黃色成對洋裝的女孩打招呼去了。

~節錄自《The Great Svelte:第三章》

第 10 天要講的是

  1. Svelte 元件的 Property
  2. Svelte 元件 Property 的預設值

  經過了這幾天的研究,現在我們已經對 Svelte 元件當中變數的改變如何帶動 HTML 的更新,以及同時更新其他相關的狀態與陳述句等略知一二了。那麼下一步想要問的,就是不同的 Svelte 元件之間應該要如何傳遞需要的變數呢?

Svelte 元件的 Property

  通常在建立一個 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 段落中。

https://ithelp.ithome.com.tw/upload/images/20230925/20120178fM1Teh39Ze.png
圖一、從父元件 (parent component) 拿到資料的子元件 (child component)

  有趣的是,Svelte 元件的 Proterty,不僅看起來像 HTML 元素的屬性 (attribute),用起來像 HTML 元素的屬性 (attribute),連連程式碼縮寫的方式都很像。也就是說,當父元件 (parent component) 的變數名稱,跟要傳入子元件 (child component) 的 Property名稱相同時:

<ChildComponent someProp={someProp} />

  可以簡單寫成:

<ChildComponent {someProp} />

Svelte 元件 Property 的預設值

  打鐵趁熱,就讓我們再討論一個與 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 />

https://ithelp.ithome.com.tw/upload/images/20230925/20120178wIuBk4Sg8F.png
圖二、子元件 (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;
      即使父元件 (parent component) 不傳資料給子元件 (child component) 也不怕了,我們有了預設值 100

https://ithelp.ithome.com.tw/upload/images/20230925/20120178rN3OWdiyPt.png
圖三、100!

那麼今天關於 Svelte 元件的 Property 就介紹到這邊了,謝謝各位讀者的支持。


上一篇
第 09 天:Svelte 中的 Javascript:陳述
下一篇
第 11 天:Svelte 的事件:事件處理
系列文
了不起的 Svelte30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言