本文同步發布於知乎專欄 https://zhuanlan.zhihu.com/p/27434018,喜歡本文的就去知乎點個贊支持下吧~
引言
該系列文章將通過創建一個組件庫來引導你學習如何構建自己的組件庫。
這是該系列的第二部分。如果你還沒有閱讀 Part 1,我推薦你先閱讀它。另外,我們將會討論有關原子設計的內容。如果你不熟悉相關概念,閱讀一些相關內容 (這兒)_ 將對你很有幫助。_
在該部分我們將討論:
-
通過
styled-components
使得我們的組件變得可配置性更強 -
添加一個調色板到我們的庫
-
使用一些
polished
的功能 -
使用
npm link
,babel
和eslint
的高效開發流程 -
將原子設計原則應用到我們的組件庫結構
原子設計 & 組件
現在我們已經完成許多初始化配置,接下來我們將花時間思考如何構建一個實用的組件庫。
為了實現這目標,我們將借用 Brad Frost 的原子設計的一些概念。這本書絕對值得一讀,你可以購買它如果你想了解更多的相關內容。但為了簡潔起見,我們將只了解一些高維抽象概念。Brad 將web UI分為五個獨立的部分:原子(atoms),分子(molecules),實體(organisms),模版(templates),頁面(pages)。
我們的組件庫將由原子和分子組成。開發者可以通過組件庫快速構建實體,模版和頁面。
Source: http://bradfrost.com/wp-content/uploads/2013/06/atomic-design.png
原子(Atoms) -> 元素(Elements)
原子是構成UI中最小的不可分割的單位。想想按鈕,鏈接,輸入框等等。在本教程中,我們統稱為它們為元素。
還記得我們創建了按鈕組件然后將其放入 /elements
目錄么? 💡
我們將從創建元素開始來寫我們的組件庫。一旦我們有足夠的元素,我們將添加一個分子。我喜歡從元素開始因為這可以讓我們的組件不過於復雜。每個元素都應該是獨立的,我們要能夠通過組合這些元素創建分子。他們(元素)應該像樂高積木一樣開箱即用,無需任何電工工具。 當我們開始構建分子,如果某些東西不合適,那么我們需要回到我們的元素去重新審視它們的設計。
分子(Molecules) -> 組件(Components)
如上所述,分子是簡單的,是原子的不同組合。接下來我們將稱這些為組件。“組件”一詞對React世界來說非常自然,但我們將以一種特殊的方式使用它。一個例子是搜索區域,它由一個標簽,一個輸入框和一個按鈕組成。另一個例子是一個下拉列表,它由一個按鈕(觸發下拉) ,一個列表和列表項組成。
好的,但是什么不是組件呢?
好問題。謝謝你的提問。一個導航欄從定義上來說不是一個組件。一個導航欄更像是一個實體。它有很多組件構建而成,能隨着組成的內容的變化而發生很大變化。一個登錄表單是另一個實體的例子。它可能包含一個標題,表單的實體標簽,輸入框和按鈕,一個重置密碼的鏈接和一個包含所有元素的div。
為什么不添加實體到組件庫?
另一個好問題。🏆添加實體到組件庫沒有問題。但當它們出現的時候我們應該拋開這些妄想。組件庫的目的是為了構建可擴展和可復用的組件。如果我們從構建許多實體開始,我們將限制用戶只能遵循我們的特定模式。我們正在添加組件以便用戶可以快速構建一致的UI。但如果他們需要一些不同的東西,或者不喜歡我們的特定的模式,那么他們可以輕易地回到元素從而構建自己的模式。
請記住有一些情景下添加實體是有意義的。比如,假設你有三個主要的應用程序用於你的業務,你希望這些應用都有一致的登錄表單。好的,那就將登錄表單的實體放入你的庫。
好,現在我們已經涵蓋了組件庫背后的很多理論。我們進入有意思的部分,開始構建。 🛠
添加有效的開發工作流
第一部分中,我們以_“… 在我們發布到npm之前,有一個用來試驗的本地測試環境將會很棒。”結束。_正如我們所承諾的,這將是我們現在所做的。
配置我們的本地環境
我們需要一個本地環境去試用我們的組件。很幸運,我有一個小應用作為此環境。你需要從GitHub上把它pull down下來並安裝依賴。
$ git clone git@github.com:alanbsmith/component-lib-playground.git
$ cd component-lib-playground
$ npm install
如果你在使用Yarn,運行yarn
。
如果你運行npm run dev
或 yarn dev
,在你的瀏覽器上打開 http://localhost:8080,然后看見“Hello, World!”,很棒! 如果你進入 src/components/App.js
文件然后修改部分JSX,你也將注意到它是熱加載更新的。這對於測試我們的庫是很棒的一點。接下里我們將把我們的應用和組件庫連接起來。
連接我們的組件庫
⚠️注意: 你可能要在一個終端窗口里保持打開組件庫,在另一個里保持打開應用。
首先我們要添加build:watch
腳本到組件庫的package.json
文件。-w
告訴了Babel注意lib
目錄下的任何變化並即時更新build
目錄下的內容。
"scripts": {
"build": "babel lib -d build",
"build:watch": "babel lib -w -d build",
"lint": "eslint lib/**; exit 0",
...
現在我們將在本地創建一個我們庫的符號鏈接。如果你想知道更多有關npm link
,這里有 一些有用的文檔。在我們組件庫的根目錄運行npm link
。你可能注意到控制台正在運行prepublish
。
現在我們將告知我們的測試應用我們將要使用符號鏈接的庫。在應用的根目錄運行:
⚠️注意: 請記住用你組件庫的名字取代 component-lib
。
npm link component-lib
就是這樣!我們准備去使用我們的組件庫在測試應用中!
添加按鈕到測試應用
在src/components/App.js
中我們將像使用其他外部庫一樣引入和調用我們的組件:
import React from 'react';
import PropTypes from 'prop-types';
import { Button } from 'component-lib'
...
const App = ({ name }) => {
return (
<div>
<h1>Hello, {name}!</h1>
<Button>Click Me!</Button>
</div>
);
};
...
一旦更新,測試應用將熱加載更新,按鈕將會出現!
添加了我們的第一個組件到測試應用!
💡 注意到我們的測試應用完全不知道 styled-components 是什么。任何人都可以不用安裝其他支持庫來使用我們的庫。這是我們把所有東西放在 devDependencies 的理由。
⚠️譯者注:譯者在運行測試應用如果不引入styled-components和polished會發生報錯,具體已經向原作者進行提問,歡迎關注后續和提出見解!
很好!現在讓我們對Button
做一些改變。如果按鈕是不同的顏色將非常棒。或許紫色?
const Button = styled.button`
background: #7E5BEF;
...
&:hover {
background: #592DEA;
}
`;
你將注意到當我們的 lib 目錄更新的時候,測試應用並沒有反映出這變化。那是因為我們需要再次運行npm run build
更新build
目錄。這不是最好的做法。每次文件更新后都需要手動重新構建有點蠢和痛苦。還記得先前我們添加的build:watch
腳本?現在我們可以使用它了。
$ npm run build:watch
咚!現在我們的組件庫每一次變化都能自動更新!🎊 當我們進行上述操作時,我們進行分屏然后運行npm run eslint:watch
從而可以立即看到我們是否有語法錯誤。你的終端看上去可能像這樣:
分別用終端打開測試應用,build:watch 腳本和 lint:watch 腳本運行。
現在我們庫的變化立即反映在應用中,我們可以輕松地進行試驗。
添加調色板
按鈕的靜態顏色限制了這個元素很多。有一個用戶可以選擇顏色的調色板將會很棒,調色板可以通過傳遞一個屬性實現。讓我們在組件庫中添加新文件colors.js
到/lib/styles
。 在里面我們添加如下內容:
module.exports = {
// light shades
white: '#FFFFFF',
snow: '#F9FAFC',
darkSnow: '#EFF2F7',
extraDarkSnow: '#E5E9F2',
// dark tones
silver: '#8492A6',
slate: '#3C4858',
steel: '#273444',
black: '#1F2D3D',
// dark shades
smoke: '#E0E6ED',
darkSmoke: '#D3DCE6',
extraDarkSmoke: '#C0CCDA',
// blue shades
lightBlue: '#85D7FF',
blue: '#1FB6FF',
darkBlue: '#009EEB',
// purple shades
lightPurple: '#A389F4',
purple: '#7E5BEF',
darkPurple: '#592DEA',
// pink shades
lightPink: '#FF7CE5',
pink: '#FF49DB',
darkPink: '#FF16D1',
// orange shades
lightOrange: '#FF9E7C',
orange: '#FF7849',
darkOrange: '#FF5216',
// green shades
lightGreen: '#29EB7F',
green: '#13CE66',
darkGreen: '#0F9F4F',
// yellow shades
lightYellow: '#FFD55F',
yellow: '#FFC82C',
darkYellow: '#F8B700',
// ui colors
info: '#1FB6FF',
success: '#13CE66',
danger: '#FF4949',
warning: '#FFC82C',
};
這些顏色來自Marvel’s styleguide。歡迎你使用自己的顏色,但這些已經足夠達到我們的目的。
現在我們將更新按鈕元素去使用這些顏色:
...
import * as colors from '../styles/colors';
const Button = styled.button`
background: ${({ bgColor }) => colors[bgColor]};
...
color: ${({ fontColor }) => colors[fontColor]};
...
&:hover {
background: ${({ hoverColor }) => colors[hoverColor]};
}
`;
Button.defaultProps = {
bgColor: 'blue',
fontColor: 'white',
hoverColor: 'darkBlue',
};
export default Button;
很酷。現在我們的用戶可以在bgColor
,fontColor
和hoverColor
屬性中使用調色板中自己想要的顏色。我們也對每個顏色屬性增加了defaultProps
,所以如果用戶不傳遞任何屬性,事情也不會變得很糟。
好!當我們的測試應用重渲染時,按鈕應該變成藍色。讓我們增加一些屬性然后聲明新的顏色。我在這里將設置為橘黃色,但你可以從調色板隨意使用顏色。
const App = ({ name }) => {
return (
<div>
<h1>Hello, {name}!</h1>
<Button
bgColor="orange"
hoverColor="darkOrange"
>
Click Me!
</Button>
</div>
);
};
很棒!
Nice!對我們用戶來說,能夠快速更新按鈕顏色而不做任何配置是非常美好的。必須要添加 hoverColor
有點煩人。但如果我們不那么做,我們將看到同樣煩人的darkBlue
。或許 polished
會有幫助?
添加一些 Polish
Polished是一個為我們提供了一些方便Sass功能的輕量級的工具集。我們已經在組件庫中安裝了它,因此我們現在只需要引入它。我們將添加darken
函數去取代hoverColor
屬性。
import styled from 'styled-components';
import { darken } from 'polished';
import * as colors from '../styles/colors';
const Button = styled.button`
background: ${({ bgColor }) => colors[bgColor]};
...
color: ${({ fontColor }) => colors[fontColor]};
...
&:hover {
background: ${({ bgColor }) => darken(0.1, colors[bgColor])};
}
`;
Button.defaultProps = {
bgColor: 'blue',
fontColor: 'white',
};
請注意我們已經完全刪除了hoverColor
屬性。現在我們可以使用darken
和bgColor
去得到我們新的懸停背景顏色。0.1
是我們使顏色變暗的量。我們也可以刪除hoverColor
屬性。
...
<Button bgColor="orange">
Click Me!
</Button>
...
好!這將會讓我們的組件更加容易使用!請再次注意測試應用並_不知道 Polished 是什么_。
Wrapping Up
⚠️注意: 我們最好保存我們的項目然后commit
。
$ git status
$ git add -A
$ git commit -m 'adds color palette and dynamic styling for Button'
現在我們已經有了一個高效的工作流,一個很棒的調色板和針對我們按鈕元素的動態樣式。在Part 3我們將繼續添加其他元素到我們的庫。
我希望這對你有幫助。如果你喜歡它,請讓我知道!歡迎分享如果你覺得這對他人有幫助!