需求:
(1)多套主题随意切换
(2)一套主题下的组件有不同的样式可供切换
(3)组件之间的样式相互独立,切换互不影响
思路:
(1)将组件的样式提取出来一套模板,主题数据嵌入模板就形成了一套主题。
抽离模板,通过容器的Context 控制样式:

(1)数据与模板对接:
1.利用css辅助函数生成样式片段
例如:
// themes/Button.style.js
import {css} from 'styled-components';
export default css`
/* 样式实现 */
`;
2.利用 styled-components 里面的 createGlobalStyle 来结合片段,生成全局样式组件
例如:
// themes/index.js
// 在这里将样式汇总,同时创建一个全局样式组件
import {createGlobalStyle} from 'styled-components';
import buttonStyle from 'Button.style.js'
import inputStyle from 'Input.style.js'
export default createGlobalStyle`
${buttonStyle}
${inputStyle}
// ...
`;
3.全局样式组件对外提供了一个接口,用于接受外部传来的主题数据,我们只需改变传入的数据,就能实现所以组件的样式切换
4.切换主题的逻辑都在顶级容器内完成
例如:
// Container/index.js
import defaultConfig from 'path/to/config/file';
import themeOneData from 'theme-data/theme1';
import themeTwoData from 'theme-data/theme2';
const themeMap = new Map([
['theme1', themeOneData],
['theme2', themeTwoData],
]);
export default function Container(props) {
const [config, setConfig] = useState(defaultConfig);
const themeData = themeMap.get(config.schema);
// 出于性能考虑,只有主题配置改变时才去重新解析数据
const currentTheme = useMemo(() => resolveThemeData(themeData, config), config);
return (
<ThemeProvider value={{...theme, setTheme: setConfig}}>
<ThemeStyle theme={currentTheme} />
{props.children}
</ThemeProvider>
);
}
.