Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP ✨pref: improve memorization #175

Open
wants to merge 3 commits into
base: alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"@emotion/react": "^11.11.4",
"@emotion/serialize": "^1.1.3",
"@emotion/utils": "^1.2.1",
"rc-util": "^5.43.0",
"use-merge-value": "^1.2.0"
},
"devDependencies": {
Expand Down
150 changes: 80 additions & 70 deletions src/factories/createStyles/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Context, useContext, useMemo } from 'react';
import useMemo from 'rc-util/lib/hooks/useMemo';
import isEqual from 'rc-util/lib/isEqual';
import { Context, useContext } from 'react';

import { Emotion, createCSS, serializeCSS } from '@/core';
import type {
Expand Down Expand Up @@ -52,78 +54,86 @@ export const createStylesFactory =

const responsiveMap = useMediaQueryMap();

const styles = useMemo(() => {
let tempStyles: ReturnStyleToUse<Input>;

// 函数场景
if (styleOrGetStyle instanceof Function) {
const { stylish, appearance, isDarkMode, prefixCls, iconPrefixCls, ...token } = theme;

// 创建响应式断点选择器的工具函数
// @ts-ignore
const responsive: ResponsiveUtil = (styles) =>
convertResponsiveStyleToString(styles, responsiveMap);
// 并赋予其相应的断点工具
Object.assign(responsive, responsiveMap);

tempStyles = styleOrGetStyle(
{
token,
stylish,
appearance,
isDarkMode,
prefixCls,
iconPrefixCls,
// 工具函数们
cx,
css: serializeCSS,
responsive,
},
props!,
) as any;
}
// 没有函数时直接就是 object 或者 string
else {
tempStyles = styleOrGetStyle as any;
}

if (typeof tempStyles === 'object') {
// 判断是否是用 reactCSS 生成的
if (isReactCssResult(tempStyles)) {
// 如果是用 reactCss 生成的话,需要用 className 的 css 做一层转换
tempStyles = toClassName(tempStyles) as any;
} else {
// 不是的话就是直接是 复合的 css object
tempStyles = Object.fromEntries(
Object.entries(tempStyles).map(([key, value]) => {
// 这里做两道转换:
// 1. 如果是用 babel 插件,则将样式的 label 设置为当前文件名 + key
// 2. 如果是 SerializedStyles ,将其用 cx 包一下转换成 className

const label = usingBabel ? `${styleFileName}-${key}` : undefined;

// 这里有可能是 { a : css` color:red ` } 也可能是 { b: { color:"blue" } } 这样的写法
if (typeof value === 'object') {
if (usingBabel) {
return [key, toClassName(value, `label:${label}`) as any];
}

return [key, toClassName(value) as any];
}

// 这里只可能是 { c: cx(css`color:red`) } , 或者 d: 'abcd' 这样的写法
return [key, value];
}),
const styles = useMemo(
() => {
let tempStyles: ReturnStyleToUse<Input>;

// 函数场景
if (styleOrGetStyle instanceof Function) {
const { stylish, appearance, isDarkMode, prefixCls, iconPrefixCls, ...token } = theme;

// 创建响应式断点选择器的工具函数
// @ts-ignore
const responsive: ResponsiveUtil = (styles) =>
convertResponsiveStyleToString(styles, responsiveMap);
// 并赋予其相应的断点工具
Object.assign(responsive, responsiveMap);

tempStyles = styleOrGetStyle(
{
token,
stylish,
appearance,
isDarkMode,
prefixCls,
iconPrefixCls,
// 工具函数们
cx,
css: serializeCSS,
responsive,
},
props!,
) as any;
}
}
// 没有函数时直接就是 object 或者 string
else {
tempStyles = styleOrGetStyle as any;
}

return tempStyles;
}, [props, theme]);
if (typeof tempStyles === 'object') {
// 判断是否是用 reactCSS 生成的
if (isReactCssResult(tempStyles)) {
// 如果是用 reactCss 生成的话,需要用 className 的 css 做一层转换
tempStyles = toClassName(tempStyles) as any;
} else {
// 不是的话就是直接是 复合的 css object
tempStyles = Object.fromEntries(
Object.entries(tempStyles).map(([key, value]) => {
// 这里做两道转换:
// 1. 如果是用 babel 插件,则将样式的 label 设置为当前文件名 + key
// 2. 如果是 SerializedStyles ,将其用 cx 包一下转换成 className

const label = usingBabel ? `${styleFileName}-${key}` : undefined;

// 这里有可能是 { a : css` color:red ` } 也可能是 { b: { color:"blue" } } 这样的写法
if (typeof value === 'object') {
if (usingBabel) {
return [key, toClassName(value, `label:${label}`) as any];
}

return [key, toClassName(value) as any];
}

// 这里只可能是 { c: cx(css`color:red`) } , 或者 d: 'abcd' 这样的写法
return [key, value];
}),
) as any;
}
}

return useMemo(() => {
const { prefixCls, iconPrefixCls, ...res } = theme;
return { styles, cx, theme: res, prefixCls, iconPrefixCls };
}, [styles, theme]);
return tempStyles;
},
[props, theme],
(prev, next) => !isEqual(prev[0], next[0], true) || prev[1] !== next[1],
);

return useMemo(
() => {
const { prefixCls, iconPrefixCls, ...res } = theme;
return { styles, cx, theme: res, prefixCls, iconPrefixCls };
},
[styles, theme],
(prev, next) => !isEqual(prev[0], next[0], true) || prev[1] !== next[1],
);
};
};
Loading