Pernah membina apl yang anda tidak mahu gunakan sendiri?
Semasa saya menjadi pembangun apl junior, saya pernah membina antara muka pengguna yang huru-hara.
Kadang-kadang apabila melihat UI tersebut, saya pernah terfikir "siapa di dunia ini yang mahu menggunakan ini? Ia kelihatan mengerikan".
Pada masa lain, terdapat "sesuatu yang tidak kena" yang saya tidak dapat nyatakan.
Walaupun saya pernah mendapatkan reka bentuk yang digilap yang menakjubkan daripada pasukan reka bentuk, apl saya tidak akan kelihatan walaupun 20% sebaik.
Saya menyedari masalah ini, dan untuk menyelesaikannya, saya melakukan penyelidikan yang mendalam di mana saya menemui konsep mempunyai sistem reka bentuk yang mengubah cara saya membina apl.
Adalah penting untuk memahami apa itu sistem reka bentuk untuk dapat memahami mengapa kita memerlukannya.
Sistem reka bentuk pada asasnya ialah sumber kebenaran terpusat untuk keputusan reka bentuk anda dan pasukan anda. Ia memberitahu anda warna apa yang hendak digunakan dan di mana? Berapakah jenis butang yang akan ada pada apl itu? Adakah kad dalam senarai anda mempunyai bayang-bayang? Semua jawapan datang daripada sistem reka bentuk.
Berikut adalah beberapa faedah mempunyai sistem reka bentuk:
UI yang konsisten: Antara muka anda tidak akan mempunyai jurang pelik di sana sini tanpa sebab. Ia akan kelihatan dan berasa seragam pada semua peranti.
Keputusan pantas: Sistem reka bentuk menguatkuasakan set kekangan tertentu untuk menjadikan keputusan anda lebih mudah, bukan lebih sukar. Lebih banyak pilihan yang anda ada, lebih banyak analisis-lumpuh yang anda hadapi.
Apl Boleh Skala: Apabila apl berkembang, sistem reka bentuk membantu dalam menggunakan semula komponen dan bukannya membina dari awal.
Fokus pada pembangunan: Anda tidak perlu lagi menekankan sama ada butang harus hijau atau biru. Sebaliknya, anda akan fokus pada perkara yang penting.
Walaupun terdapat banyak perpustakaan React Native UI di luar sana, saya menggunakan pendekatan tersuai kerana saya pernah mengalami pengalaman yang mengerikan dengan kebanyakan mereka berkenaan prestasi dan pepijat.
Satu-satunya perpustakaan yang saya andalkan untuk pendekatan saya ialah perkara bersaiz asli bertindak balas.
Sekarang sebelum anda menjerit "saiz tidak penting!", izinkan saya memberi jaminan kepada anda. Terutama sekali, apabila ia berkaitan dengan apl mudah alih.
Anda tidak mahu pengguna anda membuka apl anda, melihat logo gergasi meliputi segala-galanya dan berfikir "Apa yang buruknya..." sebelum mereka memadamkan tanpa mencuba kerana logo anda menyembunyikan butang itu.
Di situlah pentingnya reaksi-saiz-asli. Ia menjadikan apl anda responsif dengan menskalakan komponen anda agar sesuai dengan peranti. Jadi, tidak kira pengguna peranti mana pun, logo anda kekal di tempat anda meletakkannya.
Salah satu perkara pertama yang saya tentukan ialah token reka bentuk teras saya. Ini adalah blok binaan sistem reka bentuk saya. Ini termasuk palet warna, tipografi, jarak dan saiz fon.
Saya melakukan ini dengan mencipta fail theme.ts dengan kod berikut:
import {moderateScale} from 'react-native-size-matters'; // after installing custom fonts: export const FontFamily = { bold: 'Poppins-Bold', semibold: 'Poppins-SemiBold', medium: 'Poppins-Medium', regular: 'Poppins-Regular', thin: 'Poppins-Thin', }; const colors = { primary100: '#2E2C5F', primary80: '#524DA0', primary60: '#736DDF', primary40: '#A09BFF', primary20: '#DCDAFF', secondary100: '#484A22', secondary80: '#858945', secondary60: '#D9DF6D', secondary40: '#F8FCA1', secondary20: '#FDFFD4', neutral100: '#131218', neutral90: '#1D1C25', neutral80: '#272631', neutral70: '#343341', neutral60: '#3E3D4D', neutral50: '#53526A', neutral40: '#757494', neutral30: '#9C9AC1', neutral20: '#CBC9EF', neutral10: '#E8E7FF', white: '#fff', black: '#222', error: '#E7002A', success: '#3EC55F', warning: '#FECB2F', info: '#157EFB', }; const theme = { colors, fontSizes: { xxl: moderateScale(32), xl: moderateScale(28), lg: moderateScale(24), md: moderateScale(20), body: moderateScale(17), sm: moderateScale(14), xs: moderateScale(12), xxs: moderateScale(10), xxxs: moderateScale(8), }, spacing: { none: 0, xxs: moderateScale(4), xs: moderateScale(8), md: moderateScale(12), lg: moderateScale(16), xl: moderateScale(20), xxl: moderateScale(24), xxxl: moderateScale(28), }, }; export default theme;
Setelah token reka bentuk saya disediakan, saya mentakrifkan beberapa komponen boleh guna semula seperti Kotak, Tipografi dan Input. Komponen ini mematuhi token reka bentuk, memastikan konsistensi merentas apl.
Sebagai contoh, inilah cara saya mencipta komponen Kotak:
import { View, type ViewProps, type FlexAlignType, type ViewStyle, } from 'react-native'; import theme from '../styles/theme/theme'; export interface IBox extends ViewProps { backgroundColor?: keyof typeof theme.colors; p?: keyof typeof theme.spacing; pv?: keyof typeof theme.spacing; ph?: keyof typeof theme.spacing; pt?: keyof typeof theme.spacing; pb?: keyof typeof theme.spacing; pl?: keyof typeof theme.spacing; pr?: keyof typeof theme.spacing; m?: keyof typeof theme.spacing; mv?: keyof typeof theme.spacing; mh?: keyof typeof theme.spacing; mt?: keyof typeof theme.spacing; mb?: keyof typeof theme.spacing; ml?: keyof typeof theme.spacing; mr?: keyof typeof theme.spacing; gap?: number; flex?: number; flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse'; alignItems?: FlexAlignType; justifyContent?: | 'center' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'; rounded?: boolean; } export default function Box({ backgroundColor, p, pv, ph, pt, pb, pr, pl, m, mv, mh, mt, mb, ml, mr, children, style, flex, alignItems, justifyContent, flexDirection = 'column', rounded = false, gap = undefined, ...rest }: IBox) { const getMargin = () => { const obj: any = {}; if (m) { obj.margin = theme.spacing[m]; return obj; } if (mt) obj.marginTop = mt ? theme.spacing[mt] : 0; if (mb) obj.marginBottom = mb ? theme.spacing[mb] : 0; if (ml) obj.marginLeft = ml ? theme.spacing[ml] : 0; if (mr) obj.marginRight = mr ? theme.spacing[mr] : 0; if (mv) obj.marginVertical = theme.spacing[mv]; if (mh) obj.marginHorizontal = theme.spacing[mh]; return obj; }; const getPadding = () => { const obj: any = {}; if (p) { obj.padding = theme.spacing[p]; return obj; } if (pt) obj.paddingTop = pt ? theme.spacing[pt] : 0; if (pb) obj.paddingBottom = pb ? theme.spacing[pb] : 0; if (pl) obj.paddingLeft = pl ? theme.spacing[pl] : 0; if (pr) obj.paddingRight = pr ? theme.spacing[pr] : 0; if (pv) obj.paddingVertical = theme.spacing[pv]; if (ph) obj.paddingHorizontal = theme.spacing[ph]; return obj; }; const boxStyles: ViewStyle[] = [ { backgroundColor: backgroundColor ? theme.colors[backgroundColor] : undefined, flex, justifyContent, alignItems, flexDirection, borderRadius: rounded ? 10 : 0, gap, }, getMargin(), getPadding(), style, ]; return ( <View style={boxStyles} {...rest}> {children} </View> ); }
Saya menggunakan komponen Kotak yang baru dicipta ini sebagai pengganti View. Ia membolehkan saya menggayakannya dengan pantas melalui prop (dan memberi cadangan jika anda menggunakan skrip taip) seperti:
Berikut ialah contoh cara saya mencipta komponen Tipografi yang saya gunakan dan bukannya komponen React Native's Text:
import React from 'react'; import {Text, type TextProps} from 'react-native'; import theme, {FontFamily} from '../styles/theme/theme'; export interface ITypography extends TextProps { size?: keyof typeof theme.fontSizes; color?: keyof typeof theme.colors; textAlign?: 'center' | 'auto' | 'left' | 'right' | 'justify'; variant?: keyof typeof FontFamily; } export default function Typography({ size, color, textAlign, children, style, variant, ...rest }: ITypography) { return ( <Text {...rest} style={[ { color: color ? theme.colors[color] : theme.colors.white, textAlign, fontSize: size ? theme.fontSizes[size] : theme.fontSizes.body, fontFamily: variant ? FontFamily[variant] : FontFamily.regular, }, style, ]}> {children} </Text> ); }
Berikut ialah pratonton sejauh mana saya dapat menambah gaya pada komponen Tipografi tersuai saya:
Daripada mengimport tema berulang kali, saya menjadikan kod saya lebih mudah dibaca dengan mencipta cangkuk useTheme tersuai yang saya panggil di mana-mana dalam apl untuk menambah gaya yang mematuhi tema saya.
Untuk melakukan ini, saya memanfaatkan API Konteks React untuk lulus tema saya dalam apl.
Saya mencipta fail ThemeProvider.tsx dan di dalamnya tentukan ThemeContext dan ThemeProvider untuk membungkus komponen apl saya di dalamnya. Ini kodnya:
import React, {type PropsWithChildren, createContext} from 'react'; import theme from './theme'; export const ThemeContext = createContext(theme); export default function ThemeProvider({children}: PropsWithChildren) { return ( <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider> ); }
Kemudian, dalam komponen Apl saya:
export default function App() { return ( <ThemeProvider> <AppNavigation /> </ThemeProvider> ); }
Sekarang seluruh apl saya mempunyai akses kepada ThemeContext, saya mencipta cangkuk useTheme saya:
import {useContext} from 'react'; import {ThemeContext} from '../styles/theme/ThemeProvider'; export default function useTheme() { const theme = useContext(ThemeContext); return theme; }
Kini saya boleh mengakses tema saya di mana-mana sahaja dengan memanggil cangkuk useTheme seperti:
const theme = useTheme(); // example usage: theme.colors.primary100; theme.spacing.md; theme.fontSizes.lg;
Untuk melaksanakan mod gelap, dalam fail theme.ts, saya menambah palet warna lain yang mengandungi warna untuk mod gelap.
export const darkTheme = { // define dark mode colors here keeping the keys same as the light mode only changing the values. }
Then, in ThemeProvider, I simply check user settings and switch the theme like so:
<p>import {useColorScheme} from 'react-native';</p> <p>export default function ThemeProvider({children}: PropsWithChildren) {<br> const isDarkMode = useColorScheme() === 'dark';<br> return (<br> <ThemeContext.Provider value={isDarkMode ? darkTheme : theme}>{children}</ThemeContext.Provider><br> );<br> }</p>
Following this clear structured approach has brought much needed clarity, consistency, and aesthetics in my app while also sped up my development speed by at least 10x since I no longer have to dwell over design decisions.
I encourage you to try this approach and let me know what you guys think in the comments. Maybe improve it a little bit eh?
Atas ialah kandungan terperinci Cara saya menyediakan Sistem Reka Bentuk untuk Projek Asli React saya untuk Pembangunan Lebih Pantas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!