使用主题
部件的主题 key
Dojo 的主题框架使用“部件主题 key” 概念将重写的样式与对应部件的相关样式关联。覆盖的样式通常在主题中指定;但如果需要,也可以直接传给 theme 中间件的 classes 属性。
一个部件的主题 key 的确切格式为:
{package-name}/{widget-css-module-name}
其中 package-name 是项目 package.json 中 name 属性的值,widget-css-module-name 是部件使用的主 CSS 模块的文件名(不包括 .m.css 扩展名)。
主题 key 示例
给定如下项目:
package.json
{
	"name": "my-app"
}
遵循部件的 CSS 模块命名规范时,一个 src/widgets/MyWidget.ts 使用的 CSS 模块名类似于 src/styles/MyWidget.m.css。因此 MyWidget 的主题 key 为:
my-app/MyWidget
此处,部件的名称与其 CSS 模块文件的名称相同,但是开发人员要注意,不要将部件的主题 key 误认为就是部件的 TypeScript 类名。
再看第二个部件,没有遵循 CSS 模块的命名规范,如 src/widgets/BespokeWidget.ts 使用的 CSS 模块为 src/styles/BespokeStyleSheet.m.css,则部件的主题 key 应改为:
my-app/BespokeStyleSheet
编写主题
主题就是一个 TypeScript 模块,会导出一个默认对象,其中将部件主题 key 映射到导入的类型化的 CSS 模块上。主题中的 CSS 模块与部件直接使用的常规模块相同。一旦应用程序应用了主题,则主题定义对象中的主题 key 标识的每一个部件的样式,都会被主题 key 对应的 CSS 模块中的样式覆盖。
以下是 MyWidget 部件完整主题中的一个简单示例(使用默认的 CSS 模块 MyWidget.m.css),位于 my-app 项目中:
src/themes/myTheme/styles/MyWidget.m.css
.root {
	color: blue;
}
src/themes/myTheme/theme.ts
import * as myThemedWidgetCss from './styles/MyWidget.m.css';
export default {
	'my-app/MyWidget': myThemedWidgetCss
};
此处,MyWidget 遵循命名规范,将主样式类命名为 root,这样 myTheme 就可以被 src/themes/myTheme/styles/MyWidget.m.css CSS 模块中的 root 类覆盖掉。
通过主题 key my-app/MyWidget,主题将新的 root 样式类关联到 MyWidget 上。当应用 myTheme 主题后,MyWidget 会将其颜色设置为蓝色,且不会再接收其初始 CSS 模块的 root 类中定义的其他样式。
为第三方部件搭建主题
应用程序的主题可能需要包含第三方部件使用的样式,比如Dojo 自带部件库中提供的样式。
@dojo/cli-create-theme 中提供了一些工具,使用 dojo create theme CLI 命令,能为第三方部件快速生成主题脚手架。可通过以下方式在应用程序中安装:
npm install --save-dev @dojo/cli-create-theme
然后在项目根目录下按如下方式使用:
dojo create theme -n {myThemeName}
运行此命令,会在询问两个问题后开始创建 myThemeName 主题:
- What Package to do you want to theme?
- 答案应该是包含第三方部件的所有包,如 
@dojo/widgets。本命令会继续询问更多的包,直到用户结束此操作。 
 - 答案应该是包含第三方部件的所有包,如 
 - Which of the {third-party-package} theme files would you like to scaffold?
- 在回答第一个问题时,会显示第三方包中所有可主题化的部件。然后用户在其中选择一部分兼容的部件包含到输出的主题中,通常只选择在当前应用程序中实际用到的部件,确保主题足够小。
 
 
命令成功执行后,会在当前项目中创建几个文件:
src/themes/{myThemeName}/theme.tssrc/themes/{myThemeName}/{third-party-package}/path/to/{selectedWidget}.m.css
为所有 {selectedWidget} 创建的主题 CSS 模块都提供了可主题化的 CSS 选择器,然后就可以为 {myThemeName} 填充合适的样式规则。
兼容的包
任何包含 theme 目录的第三方包都是兼容的,其中既包含部件的 CSS 模块文件(*.m.css),也包含对应的编译后的定义文件(*.m.css.js - 详情参见分发主题)。
例如:
node_modules
└── {third-party-package}
    └── theme
        │   {widget}.m.css
        │   {widget}.m.css.js
分发主题
Dojo 的 cli-build-theme 提供了一个 CLI 命令,构建的主题可分发给多个应用程序使用。它会创建出以各种不同方式使用主题所需的所有文件。
注意,当使用 dojo create theme 搭建新的主题时,并不需要使用 dojo build theme,因为所有相关文件都已就位。这主要用于使用 @dojo/cli-build-app 或 @dojo/cli-build-widget 构建项目时来构建主题。
要使用此工具,在需要主题化的项目下安装 @dojo/cli-build-theme:
npm install --save-dev @dojo/cli-build-theme
然后构建主题,请运行命令,并指定一个主题名以及一个可选的发布版本号:
dojo build theme --name={myThemeName} --release={releaseVersion}
如果没有指定 release,则会使用 package.json 中的当前版本号。
运行该命令后,会在项目中创建一个 dist/src/{myThemeName} 文件夹,其中包含:
- 一个主题的 
index.js文件,会被导入并用于主题化应用程序或兼容的部件 - 主题中所有部件的 CSS 模块文件(
.m.css)。这些文件可以通过主题组合功能直接引用,可用于基于新构建的主题来创建出自己主题的所有应用程序。 - 一个 
assets文件夹,包含主题文件夹中的所有字体和图片。 - 一个 
index.css文件,如果要使用整个主题,则需要将其导入到应用程序的main.css中。 - 支持在自定义元素(custom elements)上使用主题的其他文件:
- 一个 
{name}-{release}.js文件,会使用全局的注册器注册主题(使用<script>标签添加)。 - 一个 
{name}-{release}.css文件,使用<link rel="stylesheet">标签添加。 
 - 一个 
 
使用 Dojo 提供的主题
@dojo/themes 包提供了一组立即可用的主题,涵盖了 Dojo 自带部件库的所有部件。可以按原样使用主题库,或者作为基础组合出完整的应用程序主题。
- 
要使用主题,在项目中安装
@dojo/themes,比如使用npm i @dojo/themes命令。然后,对于常规的 Dojo 应用程序: - 
在项目的
main.css文件中导入主题的 CSS 文件:@import '~@dojo/themes/dojo/index.css'; - 
导入主题的 TypeScript 模块,然后使用:
import theme from '@dojo/themes/dojo'; render() { return w(Button, { theme }, [ 'Hello World' ]); } 
如果尝试在 Custom elements 中使用它,则安装完 @dojo/themes 之后:
- 
在
index.html中添加 Custom elements 专用的主题 CSS 文件:<link rel="stylesheet" href="node_modules/@dojo/themes/dojo/dojo-{version}.css" /> - 
在
index.html中添加 Custom elements 专用的主题 JS 文件:<script src="node_modules/@dojo/themes/dojo/dojo-{version}.js"></script>