TOÀN BỘ CODE DƯỚI ĐÂY CHỈ MANG NHIỀU Ý NGHĨA TRUYỀN ĐẠT LẠI Ý TƯỞNG, HƯỚNG ĐI TRONG VIỆC XÂY DỰNG THƯ VIỆN VÀ ĐƯỢC VIẾT ĐỂ CÓ THỂ HOÀN THÀNH NHANH NHẤT BÀI BLOG CÓ THỂ!!!
Thư viện UI là tập hơp các thành phần hay còn gọi là các Component
được xây dựng có sẵn từ trước và được tái sử dụng
trong quá trình phát triển giao diện cho một website.
Hình ảnh thực tế của các
Component
Lợi ích có được tự xây dựng thư viên UI mang lại là vô cùng hấp dẫn và nó lại càng khó từ chối khi bản thân sản phẩm mà bạn đang làm việc để xây dựng nên nó là một sản phẩm Product
. Các lợi ích cụ thể như sau:
- Dung lượng File giảm có thể lên tới 9 lần. so với sử dụng các thư viện có sẵn mà khi sử dụng thì thường phải mất thời gian sử đổi lại cho phù hợp với ngôn ngũ thiết kế của dự án
- Có thể các nhân hóa một cách tuyệt đối cho phù hợp với đội ngũ phát triển.
- Toàn quyền quản lý source code của thư viện.
- Tình đồng bộ hóa về ngôn ngữ thiết kế Component
Đổi lại những thứ như trên đổi lại chúng ta cũng phải trả một cái giá tương ứng như dưới đây:
- Mức độ thành công của thư viện phụ thuộc cực kỳ nhiều vào cách triển khai xây dưng thử viện hay cụ thể hơn là Kiến trúc của bản thân thư viên đó.
- Giai đoạn phát triển ban đầu tương đối mất thời gian
Ứng cử viên sáng giá nhất cho việc học hỏi đường lối phát triển cũng như là về mức độ hài lòng từ các lập trình ( trong đó có cả mình ) chính là Material UI
.
Ra đời từ năm 2014 và được sử dụng cực kỳ phổ biến trong các công ty startup kỳ lân trên thế giới như Airbnb
, Spotify
, Netflix
, Coursera
...
Ngoài ra còn có các thư viện đang đi lên rất nhanh khác nhưng cũng sử dụng đường lối phát triển tương tự là Charka UI
.
- Chạy được trên các dự án trên môi trường
Javascript
vàTypescript
đây là yếu tô quan trọng nhất khi xây dưng thư viện UI nói riêng và các thư việnBên thứ 3
nói chung. - Có khả năng mở rộng một cách rõ ràng, mạch lạc
- Phải có Unit Testing.
Style
lựa chọn Emotion vì có thể viết css
ngay trong javascript
.
Module bundler
lựa chọn Webpack có đóng gói các file javascript
.
Testing
lựa chọn Jest đi kèm với React Testing Library để kiểm tra phần render các Base Component
được xây dựng
-
defaultTheme
là hàm cung cấp các thông số, giá trị mặc định ban đầu chung sẽ được sử dungđồng bộ
trên toàn bộ thư viện. -
createTheme
Tạo, cập nhật sửa đổi lại các thuộc tínhdefaultTheme
như đã nói ở trên. -
makeStyles
Tiến hành ghi đè các thuộc tính có sẵn củaBase Component
từ đó tạo ra một bản sao riêng biệt để phục vụ cho một số trường hợp cần sửa đổi lạiComponent
. -
withStyles
tương tựmakeStyles
như đã nói ở trên. Nhưng cách thức sử dụng dựa trênHigh Order Component
.
Còn một vài phương thức nữa nhưng nhìn chung thì sau khi xây dựng xong các phương thức trên thì việc xây dưng nốt các phương thức còn lại chỉ là vấn đề thời gian. Cụ thể hơn là các phương liên quan đến Responsive
Đây sẽ là một biến được khai báo dạng Object
bao gồm các keys
chính component
, palette
, animationframe
, breakpoints
, transitions
sẽ được nói đến dưới đây. còn một vài keys
cũng quan trọng nhưng chỉ mang tính chất khai báo như là typography
, spacing
, zIndex
... sẽ được nói đến trong các phần của bài blog tiếp theo
components
đây là keys
chứa các thuộc tính của base component
. Ta sẽ lấy ví dụ điển hình là button
như dưới đây.
variants
là keys
nắm giữa các dạng của Button Component
. Có các giá trị mặc định là container
, outlined
, text
.
sizes
là keys
quyết định kích thước hiển thị của Button Component
. Có các giá trị mặc định là sm
, md
, lg
.
backgrounds
là keys
quyết định màu nền hiển thị của Button Component
- Đây là keys bắt buộc
phải đi cùng với keys variants="container"
.
colors
là keys
quyết định màu sắc của chữ nền hiển thị của Button Component
- Đây là keys bắt buộc
phải đi cùng với keys variants="text"
.
outlinedTheme
là keys
quyết định màu sắc của chữ, viền hiển thị củaButton Component
- Đây là keys bắt buộc
phải đi cùng với keys variants="outlined"
.
Ảnh thể hiện thiết kế điển hình của
Button Component
Ảnh chi tiết code từng
Props
của biếnButton Component
palette
là bộ màu định nghĩa sẵn cho các component
trên toàn bộ thư viện. Giúp toàn bộ thư viện có sự đồng bộ về màu sắc.
Trong quá trình thiết kế component
thường sẽ kế thừa giá trị palette
để tiện cho việc thiết kế.
Ảnh chi tiết code của
palette
Ảnh chi tiết code của bộ màu định nghĩa sẵn cho
palette
được tham khảo trực tiếp từ Material UI
animationframe
là keys
nắm giữa các dạng hiệu ứng
của các component
( nếu có ) . Có các giá trị mặc định với Button Component
là ripple
, scale
.
Ảnh chi tiết code
animationframes
củaButton Component
breakpoints
đây là keys
chứa các thông số về kích thuớc màn hình chỉ định và cung cấp thêm một vài phương thức hỗ trợ cho việc định vị khoảng giới hạn màn hình nhằm phục vụ cho việc responsive
.
Ảnh chi tiết code
breakpoints
được định nghĩa
Như có thể thấy rất rõ là values
được dùng để khai báo các mốc
kích thước màn hình nhất định.
Các mốc kích thước màn hình được tham khảo trực tiếp từ Material UI/Responsive
-
down
là biểu thị chotừ kích thước màn hình nhỏ nhất
của màn hình. -
up
là biểu thị chotừ kích thước màn hình lớn nhất
của màn hình. -
between
là biểu thị chotừ kích thước màn hình nhỏ nhất đến kích thước lớn nhất
của màn hình.
typography
đây là keys
chứa các thông số về kích thuớc kiểu chữ, phông chữ... cho toàn bộ thư viện.
Ảnh chi tiết code
typography
được định nghĩa
Tham khảo các quy tắc lựa chọn kích thước chữ của Material UI/Typography
transitions
đây là keys
chứa các thông số mặc định về thời gian thực hiện các animations
Ảnh chi tiết code
transitions
được định nghĩa
Tham khảo các quy tắc của Material UI/Transitions
Đơn giản có thể hiểu đây là phương thức dùng để thiết lập defaultTheme
mới cho toàn bộ dự án.
Phương thức này được thiết kế dựa trên recursion
cho phép nó ghi đè chính bản thân nó trước đó nhiều lần tùy thích
Ảnh chi tiết code
createTheme
được định nghĩa
Ví dụ về sử dụng
createTheme
Khởi đầu defaultTheme
chắc chắn sẽ là theme
mặc định
Ta có thể bổ sung thêm vào trong bộ palette
2 nhóm mới là ghost
và innerGhost
bằng việc kết thừa trực tiếp giá trị của defaultTheme
trước đó.
Lúc này bạn có thể kế thừa tiếp giá trị palette
ở trong overridePaletteTheme
và sử dụng nó cho việc tạo mới các biến variants
mới là ghost
và innerGhost
.
Bạn sẽ thấy sự vô lý khi ta có thể sử dụng
palette
có giá trịghost
,innerGhost
mà nó thậm trí còn chưa được tồn tại trongThemeProps
. Phần cuối sẽ trả lời.
Phương thức makeStyles
nhận vào một function
và trả ra styles
mới.
Phương thức makeStyles
cho phép người dùng ghi đè các biến
đã có từ trước nhằm phục vụ cho một số trường hợp mà ta chỉ muốn ghi đè biến
đó trong phạm vị hiện tại mà ta sử dụng.
Ví dụ về sử dụng
makeStyles
để ghi đèbiến
đã có từ trước đó củaButton Component
Có thể thấy ta thực hiện việc responsive
cho className .cds-button-sizeLg
sẽ thay đổi màu sắc trong phạm vi md
& lg
Chú ý rằng Button Component
ban đầu không hề có responsive
và việc ghi đè trên chỉ có tác dụng với các Button Component
nào nhận classes
thôi.
Có thể thấy việc đưa được useStyles
ra làm một biến sẽ có ích lợi vô cùng lớn cho việc tái sử dụng trên toàn bộ dự án. Vì ta coi nó như là một biến
mang tính chất tùy chọn.
Thêm nữa nếu ai là người khó tính thì sẽ không thể bắt lỗi được bạn vì bản chất việc bạn đưa useStyles
ra ngoài Component
sẽ khiến nó chỉ được khởi tạo một lần duy nhất
nên sẽ loại bỏ các hàm gây tốn bộ nhớ như là useCallback
hay là useMemo
để "tăng tốc"
mà vốn dĩ đã được các lập trình viên làm quá lên
trong quá trình tối ưu hiệu năng
Và cuối cùng đó là ta có thể sử dụng được hook
nằm ngoài phạm vi của component
( vì ta đang kế thừa theme
từ useContext
của ThemeProvider
). Đây là điều gần như không thể nếu viết code theo lối tư duy truyền thống.
Từ đó tăng tối đa khả năng mở rộng cũng như là việc tái sử dụng
Chi tiết code
makeStyles
styleOrCreator
là một hàm được truyền từ ngoài vào nhằm tái cấu trúc lại biến
của Button Component
. Hàm này có tham số đầu vào chính là useTheme
.
useTheme
chính mộtcustom hook
được gọi ởngoài component
ngoài ra props
là một biến tùy chọn dùng để tăng tính linh hoạt cho stylesOrCreator
Tương tư như makeStyles
thì withStyles
sẽ nhận Component
và trả ra Component
có styles
mới.
Điểm khác biết là cách sử dụng vì withStyles
thường dùng riêng biết trong một file
mà ở đó ta định nghĩa ra một component
mới và sử dụng nó như một component chính
chứ không phải mang tinh chất tuỳ thích như makeStyles
Ví dụ sử dụng
withStyles
để tạo ra một biến thể mới choButton Component
có tên làWithStylesButton
Airbnb cũng sử dụng cách như trên để tạo ra hàng loạt các biến thể của một
Button Component
từ mộtcomponent gốc
.
Chi tiết code
withStyles
Do yêu cầu về việc mở rộng và dễ dàng biết chính xác các style
có nguồn gốc từ đâu thì ta sẽ lựa chọn việc tạo ra các classNames
và css
dựa theo giá trị props
.
Hình ảnh mô tả luồng của
Button Component
hàm getButtonClassNames
sẽ nhận vào props
và trả ra các className riêng biệt
tương ứng với nó và chúng sẽ được nối thành một chuỗi với nhau. Mục đích của việc này là để có thể dễ dàng nối thêm
các className
khác từ bên ngoài component
nhằm tăng độ linh hoạt ( điển hình là Tailwindcss )
Hình ảnh chi tiết code
getButtonClassNames
Hình ảnh chi tiết code
classNames
Hình ảnh
Button Component
nhận cácprops
vàclassNames
bên ngoài
Hình ảnh các
className
được tách riêng và nối thành chuỗi
Hình ảnh
css
củaroot
Hình ảnh
css
của cácprops
Hình ảnh
css
của cácclassName
truyền từ ngoài vào
hàm getButtonCSS
sẽ nhận vào props
và theme
rồi cho ra các styles
tương ứng
Hình ảnh chi tiết code
getButtonCSS
Đây là một vấn đề mà ở Material UI v4
trước đây không làm được và như đã thấy ở trên mục 3.3
thì mọi người sẽ thắc mắc là khai báo các biến variants
bao gồm container
, text
, outlined
thì việc mở rộng thêm các key
mới thì ta sẽ làm như nào ? vấn đề nằm ở cách mà ta khai báo typescript
cho từng keys
tương ứng.
Thử xem phản ứng của variant
có không có ghost
là giá trị mặc định có trong typescript
typescript
báo cho ta thấy rằng ta đang nhập vào một biến không hề được khai báo trước. Mặc dù trước đó ta có thể đã tạo cho variants
một key
là ghost
.
Gần như không có cách nào để có thể khai báo thêm ghost
khi ta đã cố định biến variant
với typescript
trước đó.
Vấn đề kiên quyết đặt ra ở đây là ta phải buộc cho typescript
phải chấp nhận
và gợi ý
cho ta khi ta sử dụng biến variant
Vậy nếu không thể ghi đè nó ở thời điểm khởi tạo
thì hãy khai báo thêm ở thời điểm cuối cùng
.
Hiểu đơn giản là những thứ bạn nhìn thấy từ typescript
cho bạn thấy qua các thông báo là kết quả của những gì mà sau khi thực hiện biên dịch
code và từ đây ta có thể thực hiện khai báo bổ sung cho variant
.
Hình ảnh mô tả
ButtonBaseProps
củaButton Component
Hình ảnh mô tả
ButtonBaseVariant
Để có thể tạo thêm được biến
mới vào trong variants
ta cần tạo một interface ButtonPropsVariantOverrides = {}
và các giá trị mới được thêm vào sẽ được nạp vào đó
Hình ảnh mô tả
ButtonPropsVariantOverrides
Tiến hành ghi đè ButtonPropsVariant
thông qua ButtonPropsVariantOverrides
Lưu ý là việc khai báo ghost: true
có ý nghĩa là cho phép ghost
được phép hoạt động, dẫn đến là ví dụ nếu đặt container: false
thì container
sẽ không được phép hoạt động ( OverridableStringUnion
chịu trách nhiệm cho việc làm trên ).
Đây là kết quả so sánh hiệu năng, dung lương của thư viện trên với các thư viện Material UI V5, Marterial ui V4.