对不起,antd的Grid组件,element的Layout组件?过时了!

对不起,antd的Grid组件,element的Layout组件?过时了!前言 现在国内国外主流B端框架都会有一个叫布局的组件,如下图: antd的布局组件示例如下: element plus 布局组件示例如下: 用过的同学都知道,这些组件主要是帮助我们布局的,并且可以设置

前言

这个组件github地址:github.com/lio-mengxia…

现在国内国外主流B端框架都会有一个叫布局的组件,如下图:

antd的布局组件示例如下:

image.png

element plus 布局组件示例如下:

image.png

用过的同学都知道,这些组件主要是帮助我们布局的,并且可以设置在不同屏幕尺寸下布局的样式。

组件的本质就是使用flex布局,假如我们要布局成如下样式,以上的布局组件实现起来比较麻烦,不妨你们尝试一下:

image.png

开始用felx写了一版,总感觉代码非常不优雅,条件判断很多,后来一想,我们是新项目,不兼容ie的,为啥不用grid布局呢,但是grid布局纯写css并不难,怎么把其封装成一个通用组件,并且使用起来要:

替代antd的grid组件! element plus 的layout组件!

问题就来了,市面上通用组件库都没这个组件啊,咋办,手写呗。参考开源项目 styled-css-grid,咋们用react函数式组件实现,并附有在线案例。因为代码只涉及到css封装,vue也可以借鉴然后封装自己的超强布局组件。

代码很优雅,只有两个文件。先看效果,再写源码, 一下所有案例的在线地址为: codesandbox.io/s/amazing-c…

案例一(这个案例的目的是说明我们组件具备子元素偏移的能力):

image.png

const cellStyle = {
  fontSize: "0.8em",
  border: "1px solid #999",
  background: "#f5f2f0",
  lineHeight: 1,
  color: "#905"
};
export default function App() {
  return (
    <Grid columns={3} height={200}> <Cell center middle style={cellStyle}> Top Left </Cell> <Cell center middle style={cellStyle} left={3}> Top Right </Cell> <Cell center middle style={cellStyle} left={2} top={2}> Middle </Cell> <Cell center middle style={cellStyle} top={3}> Bottom Left </Cell> <Cell center middle style={cellStyle} top={3} left={3}> Bottom Right </Cell> </Grid>
  );
}

案例2(这个案例说明我们的组件有任意分隔栅格布局的能力):

image.png

import { flatMap, range } from "lodash-es";

const cellStyle = {
  fontSize: "0.8em",
  border: "1px solid #999",
  background: "#f5f2f0",
  lineHeight: 1,
  color: "#905"
};

const rows = (counts) =>
  flatMap(counts, (number) =>
    range(number).map((i) => (
      <Cell center middle style={cellStyle} width={12 / number} key={`${number}_${i}`}> {i + 1}/{number} </Cell>
    ))
  );

const TraditionalGrid = () => (
  <article> <Grid columns={12} minRowHeight="45px"> {rows([12, 6, 4, 2, 1])} </Grid> </article>
);

案例三(代表我们组件具有奇形怪状的能力):

image.png

当然我们也具备本身flex的左对齐,右对齐,中间对齐这些功能:

image.png

以下是源码,一起交流:

实现GridLayout组件

import React, { useMemo } from 'react';
import { frGetter, autoRows, formatAreas } from '../config/functions';

const GridLayout = ({ columns, gap = '8px', columnGap, areas, minRowHeight, alignContent, rowGap, rows, justifyContent, flow, children, height = 'auto', style = {}, }: any) => {
  const mergedstyle = {
    display: 'grid', // 布局是grid布局
    height, // 设置容器高度
    gridAutoFlow: flow, // 设置容器内元素是从左往右(默认),还是从右往左
    gridAutoRows: autoRows(minRowHeight), // grid-auto-rows设置默认单元格高度
    gridTemplateRows: frGetter(rows), // 当传递一个数字时,它是指定行数的简写,平分高度,自适应。如果是例如100px,就是以这个数值为宽度
    gridTemplateColumns: frGetter(columns), // 当传递一个数字时,它是指定列数的简写,平分宽度,自适应。 默认值为 12,如果是例如100px,就是以这个数值为宽度
    columnGap, // 设置每个子元素之间列的间距
    rowGap, // 设置每个子元素之间行的间距
    areas: formatAreas(areas), // 传递一个字符串数组,例如 [“a a”,“b c”]。 默认不提供。
    justifyContent, // 决定整个内容区域在容器里面的水平位置(左中右)
    gridGap: gap, // 设置每个子元素之间的间距,默认8px
    alignContent, // 决定整个内容区域的垂直位置(上中下)
    ...style,
  };
  return <div style={mergedstyle}>{children}</div>;
};

export default React.memo(GridLayout);

Cell组件

import React from 'react';

const middleStyle = (middle) => {
 if (middle) {
   return {
     display: 'inline-flex',
     flexFlow: 'column wrap',
     justifyContent: 'center',
     justifySelf: 'stretch',
   };
 }
};

const Cell = ({ width = 1, height = 1, area, middle, style = {}, left, top, center, children }: any) => {
 const mergedstyle: any = {
   height: '100%',
   minWidth: 0,
   gridColumnEnd: `span ${width}`, // 使用 grid-column-end 属性设置网格元素跨越多少列,或者在哪一列结束。
   gridRowEnd: `span ${height}`, // grid-row-start 属性指定哪一行开始显示网格元素
   gridColumnStart: left, // grid-column-start 属性定义了网格元素从哪一列开始
   gridRowStart: top, // grid-row-end 属性指定哪一行停止显示网格元素,或设置跨越多少行
   textAlign: center && 'center',
   ...middleStyle(middle),
   ...style,
 };
 if (area) mergedstyle.gridArea = area;
 return <div style={mergedstyle}>{children}</div>;
};

export default React.memo(Cell);

工具函数:

export const autoRows = (minRowHeight = '20px') => `minmax(${minRowHeight}, auto)`;

export const frGetter = (value) => {
 if (!value) return;
 return typeof value === 'number' ? `repeat(${value}, 1fr)` : value;
};

export const formatAreas = (areas) => areas && areas.map((area) => `"${area}"`).join(' ');

今天的文章对不起,antd的Grid组件,element的Layout组件?过时了!分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/23571.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注