Antd-布局组件

112 阅读4分钟

一.Diverder 分割线

1.border-block-start

www.w3schools.com/cssref/css_… 设置border开始边的样式,开始边的确定依赖于block direction

[`&-horizontal${componentCls}-with-text`]: {
    display: 'flex',
    alignItems: 'center',
    margin: `${unit(token.dividerHorizontalWithTextGutterMargin)} 0`,
    color: token.colorTextHeading,
    fontWeight: 500,
    fontSize: token.fontSizeLG,
    whiteSpace: 'nowrap',
    textAlign: 'center',
    borderBlockStart: `0 ${colorSplit}`,

    '&::before, &::after': {
      position: 'relative',
      width: '50%',
      borderBlockStart: `${unit(lineWidth)} solid transparent`,
      // Chrome not accept `inherit` in `border-top`
      borderBlockStartColor: 'inherit',
      borderBlockEnd: 0,
      transform: 'translateY(50%)',
      content: "''",
    },
  },

2. padding-inline / margin-inline

padding-inline: Set the padding on both sides in the inline direction(横轴方向) margin-inline: Set the margin on both sides in the inline direction

The related CSS properties writing-mode and direction define inline direction. This affects where the start and end of an element is and the result of the padding-inline/margin-inline property. For pages in English, block direction is downward and inline direction is left to right.

2.1 padding-block / margin-block

padding-block: Set the padding on both sides in the block direction(纵轴方向) margin-block: Set the margin for both sides in the block direction

3. 对象内根据条件确定有无属性

const innerStyle: React.CSSProperties = {
    ...(hasCustomMarginLeft && { marginLeft: memoizedOrientationMargin }),
    ...(hasCustomMarginRight && { marginRight: memoizedOrientationMargin }),
  };

{...(false)} = {}

4. em 相对单位

font-size: 14px; height:0.9em; 此高度是相对该元素字体大小

二.Flex 弹性布局

1.flex

justify | 设置元素在主轴方向上的对齐方式

align | 设置元素在交叉轴方向上的对齐方式

2.gap

The gap property defines the size of the gap between the rows and between the columns in flexbox, grid or multi-column layout

三. Grid 栅格

1. 概述

布局的栅格化系统,我们是基于行(row)和列(col)来定义信息区块的外部框架,以保证页面的每个区域能够稳健地排布起来。下面简单介绍一下它的工作原理:

  • 通过 row 在水平方向建立一组 column(简写 col)。
  • 你的内容应当放置于 col 内,并且,只有 col 可以作为 row 的直接元素。
  • 栅格系统中的列是指 1 到 24 的值来表示其跨越的范围。例如,三个等宽的列可以使用 <Col span={8} /> 来创建。
  • 如果一个 row 中的 col 总和超过 24,那么多余的 col 会作为一个整体另起一行排列。

我们的栅格化系统基于 Flex 布局,允许子元素在父节点内的水平对齐方式 - 居左、居中、居右、等宽排列、分散排列。子元素与子元素之间,支持顶部对齐、垂直居中对齐、底部对齐的方式。同时,支持使用 order 来定义元素的排列顺序。

布局是基于 24 栅格来定义每一个『盒子』的宽度,但不拘泥于栅格。

2. 函数组件forceUpdate

export default function useForceUpdate() {
  const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
  return forceUpdate;
}

3. 发布订阅模式

const getResponsiveMap = (token: GlobalToken): BreakpointMap => ({
  xs: `(max-width: ${token.screenXSMax}px)`,
  sm: `(min-width: ${token.screenSM}px)`,
  md: `(min-width: ${token.screenMD}px)`,
  lg: `(min-width: ${token.screenLG}px)`,
  xl: `(min-width: ${token.screenXL}px)`,
  xxl: `(min-width: ${token.screenXXL}px)`,
});

export default function useResponsiveObserver() {
  const [, token] = useToken();
  const responsiveMap: BreakpointMap = getResponsiveMap(validateBreakpoints(token));

  // To avoid repeat create instance, we add `useMemo` here.
  return React.useMemo(() => {
    const subscribers = new Map<Number, SubscribeFunc>();
    let subUid = -1;
    let screens = {};

    return {
      matchHandlers: {} as {
        [prop: string]: {
          mql: MediaQueryList;
          listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
        };
      },
      dispatch(pointMap: ScreenMap) {
        screens = pointMap;
        subscribers.forEach((func) => func(screens));  //触发订阅函数更新
        return subscribers.size >= 1;
      },
      subscribe(func: SubscribeFunc): number {
        if (!subscribers.size) this.register();  //第一次订阅前先注册(即先生成订阅的内容)
        subUid += 1;
        subscribers.set(subUid, func);
        func(screens);
        return subUid;  //返回订阅id
      },
      unsubscribe(paramToken: number) {
        subscribers.delete(paramToken);
        if (!subscribers.size) this.unregister();  //如果所有的订阅都取消了,则注销(即删除要订阅的内容)
      },
      unregister() {
        Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
          const matchMediaQuery = responsiveMap[screen];
          const handler = this.matchHandlers[matchMediaQuery];
          handler?.mql.removeListener(handler?.listener);  //无人订阅,则取消监听
        });
        subscribers.clear();
      },
      register() {
        Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
          const matchMediaQuery = responsiveMap[screen];
          const listener = ({ matches }: { matches: boolean }) => {
            this.dispatch({
              ...screens,
              [screen]: matches,
            });
          };
          const mql = window.matchMedia(matchMediaQuery);
          mql.addListener(listener);
          this.matchHandlers[matchMediaQuery] = {
            mql,
            listener,
          };

          listener(mql);
        });
      },
      responsiveMap,
    };
  }, [token]);
}

The [Window] interface's matchMedia()  method returns a new [MediaQueryList] object that can then be used to determine if the [document] matches the [media query] string, as well as to monitor the document to detect when it matches (or stops matching) that media query.

  • [addListener()]

Adds to the MediaQueryList a callback which is invoked whenever the media query status—whether or not the document matches the media queries in the list—changes. This method exists primarily for backward compatibility; if possible, you should instead use [addEventListener()] to watch for the [change] event.

function useBreakpoint(refreshOnChange: boolean = true): ScreenMap {
  const screensRef = useRef<ScreenMap>({});
  const forceUpdate = useForceUpdate();
  const responsiveObserver = useResponsiveObserver();

  useLayoutEffect(() => {
    const token = responsiveObserver.subscribe((supportScreens) => {
      screensRef.current = supportScreens;
      if (refreshOnChange) {
        forceUpdate();
      }
    });

    return () => responsiveObserver.unsubscribe(token);
  }, []);

  return screensRef.current;
}

4. 通过解构获得不变化的值

  // "gutters" is a new array in each rendering phase, it'll make 'React.useMemo' effectless.
  // So we deconstruct "gutters" variable here.
  const [gutterH, gutterV] = gutters;

  const rowContext = React.useMemo<RowContextState>(
    () => ({ gutter: [gutterH, gutterV] as [number, number], wrap }),
    [gutterH, gutterV, wrap],
  );

5.row-gap

The row-gap property defines the size of the gap between the rows in a grid layout.

6.order

The order CSS property sets the order to lay out an item in a flex or grid container. Items in a container are sorted by ascending order value and then by their source code order. Items not given an explicit order value are assigned the default value of 0.

7.inset-inline-start

Set the distance to the parent element from the start of a positioned

element in the inline direction

The inset-inline-start property sets the distance between the start of an element and the parent element in the inline direction.

The inset-inline-end property sets the distance between the end of an element and the parent element in the inline direction.