前面學習了如何撰寫元件並添加樣式,具備了基礎撰寫元件的能力,接下來兩個章節都會打鐵趁熱來製作一個實際且極具代表性的元件 —— 「按鈕」。
網站中要用到許多種類的按鈕,但每個按鈕都創立一個元件又難以管理,像是: <a>
按鈕、 <button>
按鈕……而按鈕的樣式更是千變萬化,像是:實心、外框、幽靈、底線連結、資訊、警告、危險、成功……如果每個按鈕都寫個元件也太累人了吧!於是希望能夠運用先前所學,撰寫一個「通用按鈕元件」,並且藉由傳入元件的 Props 來創建對應按鈕元件 —— 「 Button.astro
」。
首先這個按鈕將會接收按鈕連結、樣式、大小等自訂的 Props,並且使用其餘參數將任何剩餘的 Props 給解構出來並放到標籤上:
---
const {href, theme, size, ...rest } = Astro.props
---
<a href={href} {...rest}>
<slot/>
</a>
由於並不是任何按鈕都有連結,因此可以透過動態標籤來決定標籤的種類,如果存在 href
便是 <a>
標籤,反之則是 <button>
標籤:
---
const {href, theme, size, ...rest } = Astro.props
const Element = href ? 'a' : 'button'
---
<Element href={href} {...rest}>
<slot/>
</Element>
預設將會套用 btn
樣式並且依照傳入的內容來決定按鈕風格與尺寸的樣式:
---
const {href, theme, size, ...rest } = Astro.props
const Element = href ? 'a' : 'button'
const themeClass = theme ? `btn--${theme}` : 'btn--primary'
const sizeClass = size ? `btn--${size}` : 'btn--md'
---
<Element href={href} class:list={['btn', themeClass, sizeClass]} {...rest}>
<slot/>
</Element>
接著只需要撰寫對應的按鈕風格即可:
<style>
/* 自行編寫樣式 */
.btn {}
.btn:hover {}
.btn--primary {}
.btn--secondary {}
.btn--sm {}
.btn--md {}
.btn--lg {}
</style>
這樣 Button.astro
超級按鈕就完成了!輸入對應的 Props 與 Slot,該元件就會產生出對應種類的按鈕。
最後再為元件的 Props 添加 TypeScript。
interface Props {
href?: string;
size?: "sm" | "md" | "lg";
theme?:
| "primary"
| "secondary"
}
至於標籤的型別實作我想與 Polymorphic type 有關,但我暫且看不懂這個 helper 的用法😅,如果你知道的話歡迎發言分享。
在本章節綜合了先前「基礎元件」與「樣式」兩章節的內容,打造出一個通用的網頁按鈕元件,一起來實作看看吧。按鈕是網頁極具代表性的元件之一,下一章節講解整合 Tailwind 也會以這個例子出發,敬請期待!