首页 >web前端 >js教程 >我如何为我的 React Native 项目设置设计系统以加快开发速度

我如何为我的 React Native 项目设置设计系统以加快开发速度

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-06 20:41:021083浏览

曾经构建过您不想自己使用的应用程序吗?

当我还是一名初级应用程序开发人员时,我曾经构建混乱的用户界面。

有时候,当看到这些 UI 时,我曾经想“世界上谁会想使用这个?它看起来很糟糕”。

其他时候,只是有些“不对劲的地方”我无法指出。

虽然我曾经从设计团队那里获得过令人惊叹的精美设计,但我的应用程序看起来连 20% 都没有那么好。

我意识到了这个问题,为了解决这个问题,我深入研究了这个问题,其中我发现了一个设计系统的概念,它改变了我构建应用程序的方式。

设计系统这个神奇的东西是什么?

理解设计系统是什么至关重要,这样才能理解我们为什么需要它。

设计系统基本上是您和您的团队设计决策的集中事实来源。它告诉您要使用什么颜色以及在哪里使用?该应用程序将有多少种类型的按钮?您列表中的卡片会有阴影吗?所有的答案都来自于设计系统。

以下是拥有设计系统的一些好处:

  • 一致的用户界面:您的界面不会无缘无故地到处都有那些奇怪的间隙。它在所有设备上的外观和感觉都是统一的。

  • 快速决策:设计系统强制执行一组特定的约束,使您的决策更容易,而不是更困难。你拥有的选择越多,你遇到的分析瘫痪就越多。

  • 可扩展的应用程序:随着应用程序的增长,设计系统有助于重用组件,而不是从头开始构建。

  • 专注于开发:您不再需要强调按钮应该是绿色还是蓝色。相反,您将专注于重要的事情。

工具和库

虽然有大量的 React Native UI 库,但我使用自定义方法,因为我在其中大多数库的性能和错误方面都有过可怕的经历。

我的方法唯一依赖的库是react-native-size-matters。

现在,在您尖叫“尺寸并不重要!”之前,让我向您保证,尺寸确实重要。尤其是在移动应用程序方面。

您不希望用户打开您的应用程序,看到一个覆盖所有内容的巨大徽标,然后在删除之前思考“丑陋的是什么......”,甚至不尝试就删除,因为您的徽标隐藏了按钮。

这就是react-native-size-matters 可以发挥作用的地方。它通过缩放组件以适应设备来使您的应用程序具有响应能力。因此,无论用户使用哪种设备,您的徽标都会准确地保留在您放置的位置。

设置主题

我定义的第一件事就是我的核心设计标记。这些是我的设计系统的构建模块。其中包括调色板、版式、间距和字体大小。

我通过使用以下代码创建 theme.ts 文件来实现此目的:


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;


创建可重用组件

一旦我的设计令牌就位,我就会定义一些可重用的组件,例如 Box、Typography 和 Input。这些组件遵循设计令牌,确保整个应用程序的一致性。

例如,这是我创建 Box 组件的方法:


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>
  );
}


我使用这个新创建的 Box 组件来替代 View。它允许我通过 props 快速设计它的样式(如果您使用打字稿,则提供建议),如下所示:

How I set up Design System for my React Native Projects for  Faster Development

这是我如何创建 Typography 组件的示例,我使用它来代替 React Native 的 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>
  );
}


以下是我向自定义排版组件添加样式的速度的预览:

How I set up Design System for my React Native Projects for  Faster Development

自定义使用主题挂钩

我没有一次又一次地导入主题,而是通过创建一个自定义的 useTheme 挂钩来使代码更具可读性,我在应用程序中的任何位置调用该挂钩来添加符合我的主题的样式。

为了做到这一点,我利用 React 的 Context API 在应用程序中传递我的主题。

我创建了一个 ThemeProvider.tsx 文件,并在内部定义了 ThemeContext 和 ThemeProvider 以将我的应用程序组件包装在其中。代码如下:


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>
  );
}


然后,在我的应用程序组件内:


export default function App() {
  return (
    <ThemeProvider>
      <AppNavigation />
    </ThemeProvider>
  );
}


现在我的整个应用程序都可以访问 ThemeContext,我创建了 useTheme 挂钩:


import {useContext} from 'react';
import {ThemeContext} from '../styles/theme/ThemeProvider';

export default function useTheme() {
  const theme = useContext(ThemeContext);
  return theme;
}


现在我可以通过调用 useTheme 挂钩在任何地方访问我的主题,如下所示:


const theme = useTheme();
// example usage:
theme.colors.primary100;
theme.spacing.md;
theme.fontSizes.lg;


深色模式

为了实现深色模式,在 theme.ts 文件中,我添加了另一个包含深色模式颜色的调色板。


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>




Conclusion

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?

以上是我如何为我的 React Native 项目设置设计系统以加快开发速度的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn