前言
前面学习了如何撰写组件并添加样式,具备了基础撰写组件的能力,接下来两个章节都会趁热打铁来制作一个实际且极具代表性的组件 —— 「按钮」。
定义问题
网站中会用到许多种类的按钮,但每个按钮都新建一个组件又难以管理,像是: <a> 按钮、 <button> 按钮……而按钮的样式更是千变万化,像是:实心、外框、幽灵、下划链接、信息、警告、危险、成功……如果每个按钮都写个组件也太累人了吧!于是希望能够运用先前所学,撰写一个「通用按钮组件」,并且通过传入组件的 Props 来创建对应按钮组件 —— 「 Button.astro」。
第一步:定义 Props
首先这个按钮将会接收按钮链接、样式、尺寸等自定义的 Props,并且使用其余参数将任何剩余的 Props 给解构出来并放到标签上:
---const {href, theme, size, ...rest } = Astro.props---
<a href={href} {...rest}> <slot/></a>第二步:动态决定标签
由于并不是任何按钮都有链接,因此可以透过动态标签来决定标签的种类,如果存在 href 便是 <a> 标签,反之则是 <button> 标签:
---const {href, theme, size, ...rest } = Astro.propsconst 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,该组件就会产生出对应种类的按钮。
额外步骤:添加 Type
最后再为组件的 Props 添加 TypeScript。
interface Props { href?: string; size?: "sm" | "md" | "lg"; theme?: | "primary" | "secondary"}至于标签的类型实现我想与 Polymorphic type 有关,但我暂且看不懂这个 helper 的用法 😅,如果你知道的话欢迎发言分享。
总结
在本章节综合了先前「基础组件」与「样式」两章节的内容,打造出一个通用的网页按钮组件,一起来实现看看吧。按钮是网页极具代表性的组件之一,下一章节讲解整合 Tailwind 也会以这个例子出发,敬请期待!
延伸阅读
- Day7 - 实作按钮元件 - 相同文章同步发布于 iThome 铁人赛中