Cree una biblioteca de interfaz de usuario front-end basada en React (4) -- componentes de diseño

prefacio

        Continúe con el artículo anterior # Cree una biblioteca de interfaz de usuario front-end basada en React (3): componentes básicos Icon y Button . Continuamos agregando componentes, esta vez grabando los componentes de diseño Box y Combine.

        El código de este artículo muestra el código esquemático del núcleo principal. Consulte el repositorio para ver todos los códigos: repositorio de Gitee

Caja

        Con respecto al diseño de página, el más popular es el diseño flexible y el componente Box es una encapsulación del diseño flexible. Sin más preámbulos, vayamos al código. src/componentCree una nueva carpeta debajo de la carpeta y Boxcree un nuevo archivo en ella index.tsx:

export interface BoxProps {
  children?: ReactNode;
  direction?: 'row' | 'row-reverse' | 'column' | 'column-reverse';
  wrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
  alignItems?: 'center' | 'flex-start' | 'flex-end' | 'stretch';
  alignContent?: 'center' | 'flex-start' | 'flex-end' | 'space-between' | 'space-around';
  justifyContent?:
    | 'center'
    | 'flex-start'
    | 'flex-end'
    | 'space-between'
    | 'space-around'
    | 'stretch';
  padding?: number | string;
  width?: string;
  height?: string;
  flex?: string;
}

class Box extends PureComponent<BoxProps> {
  render() {
    const box = <BoxWrap {...this.props} />;

    return box;
  }
}

...

复制代码

        Lo anterior define algunos parámetros de recepción, que corresponden a los parámetros CSS de flex Podemos completar el componente implementando cada parámetro específico en el código. A continuación, implemente el BoxWrapcomponente:

import styled from '@emotion/styled';
import { css } from '@emotion/core';

export const BoxWrap = styleWrap({
  className: prefixCls,
})(
  styled('div')((props: any) => {
      // 要实现的内容
  }),
);
复制代码

        El estante se ha configurado, a la antigua usanza, todavía usa styleWrap para envolver una capa de estilos públicos, y usa un div dentro para emprender, el contenido que se implementará en el medio debe devolver el css que se usará, aquí está el núcleo contenido:

...
const {
    children,
    direction,
    wrap,
    justifyContent,
    alignItems,
    alignContent,
    span,
    flex,
    width,
    height,
    padding,
} = props;

...

return css`
    box-sizing: border-box;
    
    // direction
    ${direction != null &&
      css`
        flex-direction: ${direction};
      `}

    // wrap
    ${wrap != null &&
      css`
        flex-wrap: ${wrap};
      `}
      
    // justifyContent
    ${justifyContent != null &&
      css`
        justify-content: ${justifyContent};
      `}
      
    // ...
`
复制代码

        Como puede ver, se puede lograr simplemente agregando un css, que es bastante simple. Cabe explicar que las propiedades de los hijos no se declaran públicamente, sino que se styledrepresentan implícitamente después de pasar al componente generado.

        Una vez creado, se puede implementar así fuera del componente:

<Box direction="column" justifyContent="center">
    <div>1</div>
    <div>2</div>
    <div>3</div>
</Box>
复制代码

Combinar

        El componente Combine se utiliza para combinar diferentes componentes. Al igual que Box, sigue siendo un componente basado en estilos. Es una encapsulación de CSS para facilitar el diseño. No usamos flex, solo envolvemos un montón de elementos de bloque en línea en un gran div. src/componentsCree una nueva Combinecarpeta debajo, cree un nuevo archivo debajo de la carpeta index.tsx:

const Combine = ({
  children,
  sharedProps = {},
  spacing = 'smart',
  separator,
  ...rest
}: CombineProps) => {
  const { size = 'md' } = sharedProps;
  let isFirstItem: boolean;
  return (
    <CombineWrap spacing={spacing} {...rest}>
        {React.Children.map(children, (child) => (
            // 遍历child
            <>
                // 放置分隔符
                {separator && !isFirstItem ? <span className={separatorCls} key="separator">
                    {separator}
                  </span> : null
                }
                // 放置子元素
                <div className={itemCls}>
                    {React.cloneElement(child)}
                    ...
                </div>
            </>
        )}
    </CombineWrap>
  )
}
复制代码

El código anterior define las clases para elementos secundarios y separadores:

export const itemCls = prefixCls + '-item';
export const separatorCls = prefixCls + '-separator';
复制代码

        Los componentes reciben parámetros de espaciado para controlar la distancia entre los componentes asociados y también puede establecer separadores como separadores personalizados. Echemos un vistazo a CombineWrapla implementación del componente:

import styled from '@emotion/styled';
import { css } from '@emotion/core';

export const CombineWrap = styledWrap<{ spacing: string }>({
  // 接受自定义class
  className: prefixCls,
})(
  // 生成一个自定义样式包裹的div
  styled('div')((props) => {
    const {
      spacing,
      theme: { designTokens: DT },
    } = props;
    
    // spacingMap为designTokens里定义的常量
    const space = (DT as any)[spacingMap[spacing]];

    return css`
      display: inline-block;  // inlink使得各个子元素平铺排列
      vertical-align: middle;
      
      // 子元素样式
      > .${itemCls} { 
        &:focus {
          z-index: 2;
        }
        &:hover {
          z-index: 3;
        }
      }
      
      // 子元素下一个兄弟,分隔符下一个子元素,子元素下一个分隔符 统一都加上左边距,这里就是space的用法
      > .${itemCls}+.${itemCls}, > .${separatorCls}+.${itemCls}, > .${itemCls}+.${separatorCls} {
        margin-left: ${space};
      }
    `;
  }),
);

复制代码

Con respecto a las constantes de espaciado, puede definir constantes en el cuerpo del tema:

T_SPACING_COMMON_XS: '4px',
T_SPACING_COMMON_SM: '8px',
T_SPACING_COMMON_MD: '12px',
T_SPACING_COMMON_LG: '16px',
T_SPACING_COMMON_XLG: '20px',
T_SPACING_COMMON_XXLG: '24px',
T_SPACING_COMMON_XXXLG: '32px',
复制代码

Luego lo usamos en el proyecto:

<Combine>
  <Button styleType="primary">按钮组展示</Button>
  <Button>按钮组展示</Button>
  <Button>按钮组展示</Button>
  <Button disabled>按钮组展示</Button>
</Combine>
复制代码

Hasta ahora, los componentes de diseño Boxy Combinela introducción se han completado ~ Para obtener más componentes, consulte el repositorio de código: repositorio de Gitee

Referirse a

Espacio y cuadrícula de React-components
Antd

Supongo que te gusta

Origin juejin.im/post/7082686023213252616
Recomendado
Clasificación