Skip to content

Commit

Permalink
fix: 选中容器时,布局页面会闪一下
Browse files Browse the repository at this point in the history
  • Loading branch information
silinchen committed Mar 7, 2023
1 parent 789e887 commit 1e52924
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 94 deletions.
8 changes: 7 additions & 1 deletion src/cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import classNames from 'classnames';
import Context from '@/common/context';
import { VER_ALIGN_ALIAS_MAP } from '@/common/constant';
import { isValidGap, wrapUnit } from '@/utils';
import useFlexClassNames from '@/hooks/use-flex-class-names';
import { CellProps, LayoutContextProps, TypeMark } from './types';

type ICell = ForwardRefExoticComponent<CellProps> & TypeMark;
Expand All @@ -37,6 +38,7 @@ const Cell: ForwardRefRenderFunction<HTMLDivElement, CellProps> = (props, ref) =
const { prefix } = useContext<LayoutContextProps>(Context);
const clsPrefix = `${prefix}cell`;

const valiedWidth = width || style?.width
const newStyle: CSSProperties = useMemo(
() => ({
...(!block
Expand All @@ -51,16 +53,20 @@ const Cell: ForwardRefRenderFunction<HTMLDivElement, CellProps> = (props, ref) =
...(width ? { width: wrapUnit(width) } : null),
...(height ? { height: wrapUnit(height) } : null),
...(isValidGap(gap) ? { gap: wrapUnit(gap) } : null),
// 有 width 或者 style.width 的时候,设置 flexBasis 宽度
...(valiedWidth ? { flexBasis: wrapUnit(valiedWidth) } : null ),
...style,
}),
[block, direction, verAlign, width, height, gap, style],
);

const flexClassNames = useFlexClassNames(props);

return (
<div
{...others}
ref={ref}
className={classNames(clsPrefix, className, {
className={classNames(clsPrefix, className, flexClassNames, {
[`${clsPrefix}-align--${align}`]: align,
})}
style={newStyle}
Expand Down
62 changes: 11 additions & 51 deletions src/col.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import React, {
useContext,
cloneElement,
forwardRef,
isValidElement,
Children,
ForwardRefExoticComponent,
ForwardRefRenderFunction,
useMemo,
} from 'react';
import { isNumber, isString } from 'lodash-es';
import classNames from 'classnames';

import { ALIGN_ALIAS_MAP } from '@/common/constant';
import Context from '@/common/context';
import { wrapUnit, getGapVal } from '@/utils';
import useFlexClassNames from '@/hooks/use-flex-class-names';
import { ColProps, LayoutContextProps, TypeMark } from './types';

type ICol = ForwardRefExoticComponent<ColProps> & TypeMark;
Expand All @@ -37,51 +34,7 @@ const Col: ForwardRefRenderFunction<HTMLDivElement, ColProps> = (props: ColProps
const clsPrefix = `${prefix}col-flex`;
const gap = getGapVal(gridGap, gapProp);

const memorizedChildren = useMemo(() => {
return Children.map(children, (child) => {
if (isValidElement(child)) {
const {
style: childStyle,
height: childHeight,
autoFit: childAutoFit,
...otherChildProps
} = child?.props;
const { minHeight: childStyleMinHeight, ...otherChildStyle } = childStyle || {};

let flex;
// 有效的固定高度
let validHeight;
// 有效的最小高度
let validMinHeight;

if (isNumber(childHeight) || (isString(childHeight) && childHeight !== '')) {
validHeight = childHeight;
} else if (childStyleMinHeight && childStyleMinHeight !== '') {
validMinHeight = childStyleMinHeight;
}

// 如果设置了最小高, 那么 flex 伸缩能力就禁用了
if (childAutoFit || validMinHeight || validHeight) {
flex = `0 0 auto`;
} else {
flex = '1 1 0';
}

return cloneElement(child, {
...otherChildProps,
style: {
flex,
...(validMinHeight ? { minHeight: validMinHeight } : null),
...(validHeight ? { height: validHeight } : null),
...otherChildStyle,
},
});
}

return child;
});
}, [children]);

const valiedWidth = width || style?.width
const newStyle = useMemo(
() => ({
// @ts-ignore
Expand All @@ -90,14 +43,21 @@ const Col: ForwardRefRenderFunction<HTMLDivElement, ColProps> = (props: ColProps
...(width ? { width: wrapUnit(width) } : null),
...(height ? { height: wrapUnit(height), flex: '0 0 auto' } : null),
...(gap ? { gap: wrapUnit(gap) } : null),
// 有 width 或者 style.width 的时候,设置 flexBasis 宽度
...(valiedWidth ? { flexBasis: wrapUnit(valiedWidth) } : null ),
...style,
}),
[align, width, height, gap, style],
);
const flexClassNames = useFlexClassNames(props);

return (
<div {...others} ref={ref} className={classNames(className, clsPrefix)} style={newStyle}>
{memorizedChildren}
<div
{...others} ref={ref}
className={classNames(className, clsPrefix, flexClassNames)}
style={newStyle}
>
{children}
</div>
);
};
Expand Down
8 changes: 7 additions & 1 deletion src/grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import classNames from 'classnames';

import Context from '@/common/context';
import { getGapVal, wrapUnit } from '@/utils';
import useFlexClassNames from '@/hooks/use-flex-class-names';
import { GridProps, LayoutContextProps, TypeMark } from './types';

type IGrid = ForwardRefExoticComponent<GridProps> & TypeMark;
Expand All @@ -30,6 +31,7 @@ const Grid: ForwardRefRenderFunction<HTMLDivElement, GridProps> = (props, ref) =
renderItem,
rows,
cols,
width,
minWidth,
maxWidth,
...others
Expand All @@ -40,6 +42,7 @@ const Grid: ForwardRefRenderFunction<HTMLDivElement, GridProps> = (props, ref) =
const rowGap = getGapVal(gridGap, rowGapProp);
const colGap = getGapVal(gridGap, colGapProp);

const valiedWidth = width || style?.width || minWidth
const memorizedNewStyle = useMemo(() => {
let gtc = `repeat(${cols}, 1fr)`;

Expand All @@ -61,6 +64,8 @@ const Grid: ForwardRefRenderFunction<HTMLDivElement, GridProps> = (props, ref) =
gridTemplateRows: `repeat(${rows}, 1fr)`,
...(rowGap ? { gridRowGap: wrapUnit(rowGap) } : null),
...(colGap ? { gridColumnGap: wrapUnit(colGap) } : null),
// 有 width 或者 style.width 的时候,设置 flexBasis 宽度
...(valiedWidth ? { flexBasis: wrapUnit(valiedWidth) } : null ),
...style,
};
}, [cols, colGap, minWidth, maxWidth, rows, rowGap, style]);
Expand All @@ -74,11 +79,12 @@ const Grid: ForwardRefRenderFunction<HTMLDivElement, GridProps> = (props, ref) =
});
};

const flexClassNames = useFlexClassNames(props);
return (
<div
{...others}
ref={ref}
className={classNames(className, clsPrefix, {
className={classNames(className, clsPrefix, flexClassNames, {
[`${clsPrefix}-align--${align}`]: align,
[`${clsPrefix}-valign--${verAlign}`]: verAlign,
})}
Expand Down
43 changes: 43 additions & 0 deletions src/hooks/use-flex-class-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useContext } from 'react'
import classNames from 'classnames';
import { isNumber, isString } from 'lodash-es';

import Context from '../common/context';
import { LayoutContextProps } from '../types';

// 通过判断容器 props 值,给容器设置class,由 class 控制容器 flex 样式
const useFlexClassNames = (props: any) => {
const { autoFit, width, height, style } = props

const { prefix } = useContext<LayoutContextProps>(Context);
const clsPrefix = `${prefix}flex-item`;

const validWidth = width || style?.width;
const validHeight = isNumber(height) || (isString(height) && height !== '') ? height : undefined;
const validMinHeight = style?.minHeight;

let isDefault = false;
let isAutoFit = false;
let isValidWidth = false;
let isValidHeight = false;

if(autoFit) {
isAutoFit = true
} else if(validHeight || validMinHeight || validWidth) {
isValidHeight = validHeight || validMinHeight
isValidWidth = validWidth
} else {
isDefault = true
}

const classes = classNames({
[`${clsPrefix}-default`]: isDefault,
[`${clsPrefix}-auto-fit`]: isAutoFit,
[`${clsPrefix}-valid-width`]: isValidWidth,
[`${clsPrefix}-valid-height`]: isValidHeight
})

return classes
}

export default useFlexClassNames
50 changes: 9 additions & 41 deletions src/row.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import React, {
useContext,
cloneElement,
isValidElement,
forwardRef,
Children,
ForwardRefExoticComponent,
ForwardRefRenderFunction,
useMemo,
Expand All @@ -13,6 +10,7 @@ import classNames from 'classnames';
import { VER_ALIGN_ALIAS_MAP } from '@/common/constant';
import Context from '@/common/context';
import { getGapVal, wrapUnit } from '@/utils';
import useFlexClassNames from '@/hooks/use-flex-class-names';
import { LayoutContextProps, RowProps, TypeMark } from './types';

type IRow = ForwardRefExoticComponent<RowProps> & TypeMark;
Expand All @@ -36,43 +34,8 @@ const Row: ForwardRefRenderFunction<HTMLDivElement, RowProps> = (props: RowProps
const clsPrefix = `${prefix}row-flex`;
const gap = getGapVal(gridGap, gapProp);

// 暂存 children (此处用处不大,上层大部分情况有 clone children 的操作)
const memorizedChildren = useMemo(() => {
return Children.map(children, (child) => {
if (isValidElement(child)) {
const { width: childWidth, autoFit: childAutoFit, style: childStyle } = child?.props;
const { width: childStyleWidth, ...otherChildStyle } = childStyle || {};
const valiedWidth = width || style?.width

let flex;
let validWidth;

if (childWidth && childWidth !== '') {
validWidth = childWidth;
} else if (childStyleWidth && childStyleWidth !== '') {
validWidth = childStyle.width;
}

if (childAutoFit) {
flex = '0 0 auto';
} else if (validWidth) {
flex = `0 0 ${wrapUnit(validWidth)}`;
} else {
flex = '1 1 0';
}

return cloneElement(child, {
...child?.props,
style: {
flex,
width: validWidth,
...otherChildStyle,
},
});
}

return child;
});
}, [children]);

const newStyle = useMemo(
() => ({
Expand All @@ -81,14 +44,19 @@ const Row: ForwardRefRenderFunction<HTMLDivElement, RowProps> = (props: RowProps
...(width ? { width: wrapUnit(width) } : null),
...(height ? { height: wrapUnit(height) } : null),
...(gap ? { gap: wrapUnit(gap) } : null),
// 有 width 或者 style.width 的时候,设置 flexBasis 宽度
...(valiedWidth ? { flexBasis: wrapUnit(valiedWidth) } : null ),
...style,
}),
[verAlign, width, height, gap, style],
);
const flexClassNames = useFlexClassNames(props);

return (
<div {...others} className={classNames(className, clsPrefix)} style={newStyle} ref={ref}>
{memorizedChildren}
<div
{...others}
className={classNames(className, clsPrefix, flexClassNames)} style={newStyle} ref={ref}>
{children}
</div>
);
};
Expand Down
21 changes: 21 additions & 0 deletions src/scss/row-col-cell.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
flex-wrap: nowrap;
flex: 1 1 auto;
gap: var(--page-grid-gap);
// 行容器下的子容器 flex 属性,只在 validWidth 时生效
// 并且只有前两个参数 0 0,第三个参数需要根据 validWidth 设置,所以单独在子容器里面设置
> #{$biz-css-prefix}flex-item-valid-width {
flex: 0 0;
}
}

&col-flex {
Expand All @@ -48,5 +53,21 @@
flex-wrap: nowrap;
flex: 1 1;
gap: var(--page-grid-gap);
// 列容器下的子容器 flex 属性,只在 validHeight 时生效
> #{$biz-css-prefix}flex-item-valid-height {
flex: 0 0 auto;
}
}

&row-flex,
&col-flex {
> #{$biz-css-prefix}flex-item {
&-default {
flex: 1 1 0;
}
&-auto-fit {
flex: 0 0 auto;
}
}
}
}
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ export interface GridProps extends BaseProps {
* 列数
*/
cols?: number;
/**
* 单元格的宽度
*/
width?: number;
/**
* 单元格的最小宽度
*/
Expand Down

0 comments on commit 1e52924

Please sign in to comment.