From a51d72a6203b558c84616ed490f7e07e15632415 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Sat, 6 May 2023 00:23:11 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20feat:=20=E6=94=AF=E6=8C=81=20Style?= =?UTF-8?q?Provider=20container=20=E4=B8=8E=E9=BB=98=E8=AE=A4=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E9=9A=94=E7=A6=BB=E7=9A=84=E6=A0=B7=E5=BC=8F=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 需求:同一个组件想在同一个页面的两个不同地方使用,一处是正常引用,style标签插在header中,另一处是在页面中的iframe里去引入这个组件,通过styleProvider来配置插入位置 --- src/factories/createStyleProvider/index.tsx | 33 +++++---------- src/factories/createStyles/index.ts | 18 ++++----- src/functions/createInstance.ts | 45 ++++++++++----------- 3 files changed, 40 insertions(+), 56 deletions(-) diff --git a/src/factories/createStyleProvider/index.tsx b/src/factories/createStyleProvider/index.tsx index ba5a5baa..d22ce764 100644 --- a/src/factories/createStyleProvider/index.tsx +++ b/src/factories/createStyleProvider/index.tsx @@ -1,10 +1,9 @@ -import { DEFAULT_CSS_PREFIX_KEY } from '@/core'; import { createEmotion, Emotion } from '@/core/createEmotion'; import { StyleManager } from '@/types'; import { StyleProvider as AntdStyleProvider } from '@ant-design/cssinjs'; import type { StyleContextProps } from '@ant-design/cssinjs/es/StyleContext'; import { StylisPlugin } from '@emotion/cache'; -import { Context, FC, memo, ReactNode, useEffect, useMemo } from 'react'; +import { Context, FC, memo, ReactNode, useContext, useEffect, useMemo } from 'react'; export interface StyleProviderProps extends Partial< @@ -30,37 +29,25 @@ export interface StyleProviderProps children: ReactNode; } -interface DefaultProps { - prefix: string; - speedy?: boolean; - container?: Node; - defaultEmotion: Emotion; -} - -export const createStyleProvider = ( - EmotionContext: Context, - defaultProps?: DefaultProps, -): FC => +export const createStyleProvider = (EmotionContext: Context): FC => memo( ({ children, - prefix = defaultProps?.prefix || DEFAULT_CSS_PREFIX_KEY, - speedy = defaultProps?.speedy, + prefix: outerPrefix, + speedy: outSpeedy, getStyleManager, - container = defaultProps?.container, + container: outerContainer, nonce, insertionPoint, stylisPlugins, ...antdStyleProviderProps }) => { - // FIXME: 现在的解决方案比较 hack,通过修改默认传入的 defaultEmotion 的方式来实现,后续新方案里要考虑通过 context 的方式来实现 - if (container && defaultProps) { - defaultProps.defaultEmotion.sheet.container = container; - } + const defaultEmotion = useContext(EmotionContext); + + const prefix = outerPrefix ?? defaultEmotion.sheet.key; + const container = outerContainer ?? defaultEmotion.sheet.container; + const speedy = outSpeedy ?? defaultEmotion.sheet.isSpeedy; - // useEffect(() => { - // console.log(container); - // }, [container]); const emotion = useMemo(() => { const defaultSpeedy = process.env.NODE_ENV === 'development'; diff --git a/src/factories/createStyles/index.ts b/src/factories/createStyles/index.ts index 57c50030..d9b72109 100644 --- a/src/factories/createStyles/index.ts +++ b/src/factories/createStyles/index.ts @@ -1,6 +1,6 @@ -import { useMemo } from 'react'; +import { Context, useContext, useMemo } from 'react'; -import { createCSS, serializeCSS } from '@/core'; +import { Emotion, createCSS, serializeCSS } from '@/core'; import type { BaseReturnType, CSSObject, @@ -9,13 +9,12 @@ import type { ReturnStyleToUse, } from '@/types'; import { isReactCssResult } from '@/utils'; -import { EmotionCache } from '@emotion/css/create-instance'; import { convertResponsiveStyleToString, useMediaQueryMap } from './response'; import { ReturnStyles, StyleOrGetStyleFn } from './types'; interface CreateStylesFactory { - cache: EmotionCache; + EmotionContext: Context; hashPriority?: HashPriority; useTheme: () => any; } @@ -28,18 +27,19 @@ export interface CreateStyleOptions { * 创建样式基础写法 */ export const createStylesFactory = - ({ hashPriority, cache, useTheme }: CreateStylesFactory) => + ({ hashPriority, useTheme, EmotionContext }: CreateStylesFactory) => ( styleOrGetStyle: StyleOrGetStyleFn, options?: CreateStyleOptions, ) => { - // 由于 toClassName 方法依赖了用户给 createStyle 传递的 hashPriority,所以需要在这里重新生成 cx 和 toClassName 方法 - const { cx, css: toClassName } = createCSS(cache, options?.hashPriority || hashPriority); - // 返回 useStyles 方法,作为 hooks 使用 return (props?: Props): ReturnStyles => { const theme = useTheme(); + const { cache } = useContext(EmotionContext); + // 由于 toClassName 方法依赖了用户给 createStyle 传递的 hashPriority,所以需要在这里重新生成 cx 和 toClassName 方法 + const { cx, css: toClassName } = createCSS(cache, options?.hashPriority || hashPriority); + const responsiveMap = useMediaQueryMap(); const styles = useMemo(() => { @@ -103,7 +103,7 @@ export const createStylesFactory = return useMemo(() => { const { prefixCls, ...res } = theme; - return { styles, cx: cx, theme: res, prefixCls }; + return { styles, cx, theme: res, prefixCls }; }, [styles, theme]); }; }; diff --git a/src/functions/createInstance.ts b/src/functions/createInstance.ts index 726c204f..64d6313c 100644 --- a/src/functions/createInstance.ts +++ b/src/functions/createInstance.ts @@ -57,41 +57,45 @@ export interface CreateOptions { * 创建一个新的 antd-style 实例 */ export const createInstance = (options: CreateOptions) => { - const defaultKey = options.key || 'css'; + const internalOptions = { + ...options, + key: options.key ?? 'zcss', // 新建的 instance key 如果不传,则设为 zcss- 使得该 key 和 acss 不一样 + speedy: options.speedy ?? false, + }; - // TODO: 此处的 emotion 应该是 emotion context 中的 emotion,需要允许外部通过 Provider 进行修改 const emotion = createEmotion({ - key: defaultKey, - speedy: options.speedy, - container: options.container, + key: internalOptions.key, + speedy: internalOptions.speedy, + container: internalOptions.container, }); - // 将 cache 存到一个全局 - cacheManager.add(emotion.cache); - const { cache, injectGlobal, keyframes } = emotion; + const EmotionContext = createEmotionContext(emotion); - const { cx } = createCSS(cache, options.hashPriority); + const StyleProvider = createStyleProvider(EmotionContext); + + // 将 cache 存到全局管理器中 + cacheManager.add(emotion.cache); // ******* 下面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************* // const CustomThemeContext = createContext( - (options.customToken ? options.customToken : {}) as T, + (internalOptions.customToken ? internalOptions.customToken : {}) as T, ); - const styledThemeContext = options.styled?.ThemeContext; + const styledThemeContext = internalOptions.styled?.ThemeContext; const StyleEngineContext = createContext({ CustomThemeContext, StyledThemeContext: styledThemeContext, - prefixCls: options?.prefixCls, + prefixCls: internalOptions?.prefixCls, }); const useTheme = createUseTheme({ StyleEngineContext }); const createStyles = createStylesFactory({ - cache, - hashPriority: options.hashPriority, + hashPriority: internalOptions.hashPriority, useTheme, + EmotionContext, }); const createGlobalStyle = createGlobalStyleFactory(useTheme); @@ -99,21 +103,14 @@ export const createInstance = (options: CreateOptions) => { const createStylish = createStylishFactory(createStyles); const ThemeProvider = createThemeProvider({ - styledConfig: options.styled, + styledConfig: internalOptions.styled, StyleEngineContext, useTheme, }); // ******** 上面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************ // - - const EmotionContext = createEmotionContext(emotion); - - const StyleProvider = createStyleProvider(EmotionContext, { - speedy: options.speedy, - prefix: defaultKey, - container: options.container, - defaultEmotion: emotion, - }); + const { cx } = createCSS(emotion.cache, internalOptions.hashPriority); + const { injectGlobal, keyframes } = emotion; return { // ******************** //