通常情况下,您希望用户能够根据自己的偏好配置应用程序的外观。theme-switcher
是一个轻量级且高效的插件,它允许您轻松地在不同的 (s)css 文件集之间切换,并在切换到不同的主题时处理卸载每个主题的所有样式。
npm i --save @nativescript/theme-switcher
import { Dialogs } from "@nativescript/core";
import { initThemes, switchTheme } from '@nativescript/theme-switcher';
// in main.ts
initThemes({
default: () => import('theme-loader!./themes/default.scss'),
red: () => import('theme-loader!./themes/red.scss'),
green: () => import('theme-loader!./themes/green.scss'),
}, {
/* optionally pass in options here */
});
// in the button tap handler
async function onTap() {
const res = await Dialogs.action('Select theme', 'Cancel', [
'default', 'red', 'green'
])
if(res) {
switchTheme(res);
}
}
插件本身非常简单,它可以分解成几个不同的部分
index.ts
中的插件代码本身theme-loader.js
中的 webpack 加载器nativescript.webpack.js
中的 (nativescript) webpack 配置shims.d.ts
中支持导入 css/scss 文件的 TypeScript shim插件包含一个 ThemeSwitcher
类,一个导出的默认实例以及可用的方法的直接导出作为快捷方式。
切换主题时,先前选择的主题的 css 规则将使用核心中的 removeTaggedAdditionalCSS
方法清理。新的 css 规则将使用 addTaggedAdditionalCSS
添加。最后,我们通过在根视图和所有打开的模态视图上调用 _onCssStateChange()
来刷新样式。
持久化是使用核心中的 ApplicationSettings
完成的,保存最后一个主题的键是可配置的。
在 @nativescript/webpack@5+
中,css 和 scss 使用核心中的 addAdditionalTaggedCSS
和 removeAdditionalTaggedCSS
方法加载和应用,并在您自动 import './something.css'
时调用。
切换主题时,我们需要导入 css,但我们实际上不希望样式自动应用,因为在切换到其他主题时没有简单的方法删除它们。
为了简化使用,@nativescript/theme-switcher
附带了一个微小的 webpack 加载器,它将所有对 addAdditionalTaggedCSS
和 removeAdditionalTaggedCSS
的调用替换为空操作函数调用 - 禁用导入的 css/scss 的自动应用。
加载器旨在通过在其前面添加导入路径来直接在标记中使用
import "theme-loader!./path/to/some.css"
import "theme-loader!./path/to/some.scss"
以上将正常处理 some.s?css
文件,将其通过所有配置的加载器运行,最后将通过我们的 theme-loader
运行以禁用加载代码。
插件假设您正在使用 @nativescript/webpack@5+
并利用它提供的一些新功能。即,此插件有一个 nativescript.webpack.js
文件,它为 theme-loader
注册了一个新的加载器别名,从而简化了与现有 NativeScript 项目的集成。
const { resolve } = require('path');
/**
* @param {typeof import("@nativescript/webpack")} webpack
*/
module.exports = (webpack) => {
webpack.chainWebpack((config) => {
// prettier-ignore
config.resolveLoader.alias
.set('theme-loader', resolve(__dirname, 'theme-loader'))
});
};
这种方法为插件作者打开了无限的可能性。ThemeSwitcher 只是可能性的冰山一角。
TypeScript 不知道如何处理 .css
或 .scss
文件,并且在遇到以下代码时会报错
import("theme-loader!./themes.default.css");
以上对于 TypeScript 来说确实毫无意义,但由于 NativeScript 应用程序是使用 webpack 构建的 - 我们配置了规则来处理 css 和 scss 文件。
解决此问题的快速方法是在 import 语句上方添加 // @ts-ignore
,然后就完事了。
ThemeSwitcher 附带一个 shims.d.ts
文件,它让 typescript 知道以上是一个有效的模块/导入。
shim 本身包含以下内容,并且没有声明任何细节,仅用于让 TypeScript 知道这些模块。
declare module "theme-loader!*" {}
要让 TypeScript 知道 shims,请将其包含在 references.d.ts
文件中
/// <reference path="./node_modules/@nativescript/theme-switcher/shims.d.ts" />
就是这样,如果您遇到问题,请告诉我们。