参考ng-alain和delon
思路就是动态加载css文件
代码实现
-
写两套less文件,分别为light.less和dark.less
-
用相关插件将less文件转为一个js对象(less-vars-to-js 插件)
function genToJs(type) {
const ngZorroAntdStylePath = path.join(__dirname, '../node_modules/ng-zorro-antd/style');
const ngZorro = `
${fs.readFileSync(path.join(ngZorroAntdStylePath, 'color', 'colors.less'), 'utf8')}
${fs.readFileSync(path.join(ngZorroAntdStylePath, 'themes', `default.less`), 'utf8')}
`;
const packagesPath = path.join(__dirname, '../src/styles');
const ngAlain = `
${fs.readFileSync(path.join(packagesPath, `${type}.less`), 'utf8')}
`;
return lessToJs(`${ngZorro}${ngAlain}`, {
stripPrefix: true,
resolveVariables: false,
});
}
const darkThemeVars = genToJs('dark');
const lightThemeVars = genToJs('light');
-
用less插件修改modifyVars中的变量,根据主题来切换生成的对象,然后导出成css文件
function gen(type) {
return less
.render(themeContent, {
javascriptEnabled: true,
plugins: [
new LessPluginNpmImport({ prefix: '~' }),
new LessPluginCleanCSS({ advanced: true })
],
modifyVars: {
...(type === 'dark' ? darkThemeVars : lightThemeVars),
},
})
.then((data) => {
fs.writeFileSync(
// 主题样式的输出文件
`src/assets/style.${type}.css`,
data.css,
);
})
.catch((e) => {
// 记录渲染错误
console.error(type, e);
});
}
Promise.all([gen('dark'), gen('light')]).then(() => {
console.log('Success!');
});
-
动态切换css文件
onThemeChange(theme: SiteTheme): void {
if (!this.platform.isBrowser) {
return;
}
this.theme = theme;
const dom = document.getElementById('site-theme');
if (dom) {
dom.remove();
}
localStorage.removeItem('site-theme');
if (theme !== 'default') {
const el = (this.el = document.createElement('link'));
el.type = 'text/css';
el.rel = 'stylesheet';
el.id = 'site-theme';
el.href = `assets/style.${theme}.css`;
localStorage.setItem('site-theme', theme);
document.body.append(el);
}
this.updateChartTheme();
}
-
总代码如下:
const less = require('less');
const LessPluginCleanCSS = require('less-plugin-clean-css');
const LessPluginNpmImport = require('less-plugin-npm-import');
const fs = require('fs');
const path = require('path');
const lessToJs = require('less-vars-to-js');
// const darkThemeVars = require('@delon/theme/theme-dark');
// const compactThemeVars = require('@delon/theme/theme-compact');
const appStyles = 'src/styles.less'; // 应用的样式入口文件
const themeContent = `@import '${appStyles}';`;
// 根据参数来将less文件生成对应的js对象
function genToJs(type) {
const ngZorroAntdStylePath = path.join(__dirname, '../node_modules/ng-zorro-antd/style');
const ngZorro = `
${fs.readFileSync(path.join(ngZorroAntdStylePath, 'color', 'colors.less'), 'utf8')}
${fs.readFileSync(path.join(ngZorroAntdStylePath, 'themes', `default.less`), 'utf8')}
`;
const packagesPath = path.join(__dirname, '../src/styles');
const ngAlain = `
${fs.readFileSync(path.join(packagesPath, `${type}.less`), 'utf8')}
`;
return lessToJs(`${ngZorro}${ngAlain}`, {
stripPrefix: true,
resolveVariables: false,
});
}
const darkThemeVars = genToJs('dark');
const lightThemeVars = genToJs('light');
// 根据参数来生成对应的css文件
function gen(type) {
return less
.render(themeContent, {
javascriptEnabled: true,
plugins: [new LessPluginNpmImport({ prefix: '~' }), new LessPluginCleanCSS({ advanced: true })],
modifyVars: {
...(type === 'dark' ? darkThemeVars : lightThemeVars),
},
})
.then((data) => {
fs.writeFileSync(
// 主题样式的输出文件
`src/assets/style.${type}.css`,
data.css,
);
})
.catch((e) => {
// 记录渲染错误
console.error(type, e);
});
}
Promise.all([gen('dark'), gen('light')]).then(() => {
console.log('Success!');
});
参考:
delon: https://github.com/ng-alain/delon/blob/9.x/scripts/build/vars.js#L7-L33.
ng-alalin: https://github.com/ng-alain/ng-alain/blob/9.x/scripts/theme.js#L10-L34.
补充
- 切换完样式下拉框、提示信息有问题,不正常显示
- 原因: dropdown和tooltip组件等样式在组件中写的
.ant-dropdown-menu,
.ant-select-dropdown,
.ant-mention-dropdown,
.ant-dropdown,
.ant-cascader-menus {
top : 100%;
left : 0;
position : relative;
width : 100%;
margin-top : 4px;
margin-bottom: 4px;
}
.ant-tooltip{
position : relative;
}