项目背景
公司的产品是一款2B的在线教育产品,已有的客户大多数都有定制化的需求,主要包括UI主题和二次开发的功能。本文围绕的主要内容是如何基于 Ionic 2 平台提供的工具,实现灵活的多主题方案。
Ionic 2 提供的主题方案
Ionic 2 使用 $color map 的 key 作为组件的输入属性,用于设置组件的样式。$colors map 中的内容如下:
// variables.scss 文件(路径: src/theme/variables.scss )
$colors: {
primary: #387ef5,
secondary: #32db64,
danger: #f53d3d,
light: #f4f4f4,
dark: #222,
favorite: #69BB7B
};
使用示例:
<ion-item-options side="right">
<button ion-button color="primary" (click)="buttonOne(page.title)">
<ion-icon name="text"></ion-icon>
BUTTON 1
</button>
<button ion-button color="secondary" (click)="buttonTwo(page.title)">
<ion-icon name="call"></ion-icon>
BUTTON 2
</button>
</ion-item-options>
此外 $colors map 还支持字面量形式,对象内部有 base 和 contrast 属性
base: 用于标识组件的背景颜色
contract: 用于标识组件的文本颜色
备注:Ionic 框架内部使用 node_modules/ionic-angular/themes/ionic.functions.scss 中的颜色处理函数,解析 map中设置的 base 和 contrast 值。
使用示例:
$colors: (
twitter: {
base: #55acee,
contrast: #ffffff
},
facebook: {
base: #38669f;
contrast: #ffffff
}
);
切换 Ionic 的主题:
在 src/theme/variables.scss 文件中导入 Ionic 预置的黑色主题
@import "ionic.build.dark";
自定义主题
修改Variables文件中,$colors map 定义的属性值
覆写已有的变量值
自定义 Sass 变量
自定义组件样式
配置组件的mode(模式)
1.修改Variables文件中,$colors map 定义的属性值
// variables.scss 文件(路径: src/theme/variables.scss )
$colors: (
primary: #387ef5,
secondary: #32db64,
danger: #f53d3d,
light: #f4f4f4,
dark: #222,
favorite: #69BB7B,
twitter:(
base: #55acee,
contrast: #ffffff
),
facebook:(
base: #38669f,
contrast: #ffffff
)
);
<button ion-button color="facebook" (click)="buttonOne(page.title)">
<ion-icon name="text"></ion-icon>
BUTTON 1
</button>
<button ion-button color="twitter" (click)="buttonTwo(page.title)">
<ion-icon name="call"></ion-icon>
BUTTON 2
</button>
在任意自定义组件中,可以使用 color 函数获取相应的颜色值:
my-component {
background: color($colors, twitter, base);
}
2.覆写已有的变量值
$text-color: #686868;
$font-size-base: 1.6rem;
$list-ios-background-color: #ffffff;
$list-md-background-color: #ffffff;
$list-wp-background-color: #ffffff;
Ionic 中可以覆写的 Sass 变量列表:overriding-ionic-variables
3.自定义 Sass 变量
// variables.scss 文件(路径: src/theme/variables.scss )
$colors: (
...
);
$my-padding: 20px; // Custom Sass variables
4.自定义组件样式
// about.scss 文件 (路径: myApp/src/pages/about/about.scss)
page-about {
.isSuccess {
color: #1E88E5 !important;
}
.isError {
color: #D43669 !important;
}
}
about.scss 文件中的内容将会被编译到 main.css文件中
page-home .isSuccess {
color: #1E88E5 !important;
}
page-home .isError {
color: #D43669 !important;
}
5.配置组件的mode(模式)
每个平台都有对应的模式:
md (Android)
ios (iOS)
wp (Windows Phone)
md (Core – used for any platform other than the above)
我们也可以通过 Ionic 的 Config API 方便地配置 mode 下可配置字段的值,具体如下:
imports: [
IonicModule.forRoot(MyApp, {
backButtonText: "",
backButtonIcon: "md-arrow-back",
iconMode: "md",
modalEnter: "modal-md-slide-in",
modalLeave: "modal-md-slide-out",
pageTransition: "md"
});
]
以上的配置信息,用于设置在 iOS 平台下,App 的风格采用 Android material 设计。
我们也可以单独针对特定的平台,进行配置:
imports: [
IonicModule.forRoot(MyApp, {
platforms: {
android: {
backButtonText: "",
backButtonIcon: "md-arrow-back",
iconMode: "md",
modalEnter: "modal-md-slide-in",
modalLeave: "modal-md-slide-out",
pageTransition: "md",
},
ios : {
backButtonText: "Previous",
backButtonIcon: "ios-arrow-back",
iconMode: "ios",
modalEnter: "modal-ios-slide-in",
modalLeave: "modal-ios-slide-out",
pageTransition: "ios",
}
}];
此外,通过 Config API 提供的方法,我们可以在 TypeScript classes 中,方便的设置特定平台下的配置信息,具体如下:
config.set('ios', 'textColor', '#AE1245');
该方法接受三个参数:
platform (optional – ‘ios’ or ‘android’, if omitted this will apply to all platforms)
key (optional – The name of the key used to store our value I.e. ‘textColor’)
value (optional – The value for the key I.e. ‘#AE1245’)
通过 Config API 提供的 get 方法获取配置的值:
config.get('textColor');
我们也能够在组件层级,方便地配置组件,如通过 ion-tabs 的输入属性 tbasPlacement 设置 ion-tabs 组件的显示位置:
<ion-tabs tabsPlacement="bottom">
<ion-tab tabTitle="Dash" tabIcon="pulse" [root]="tabRoot"></ion-tab>
</ion-tabs>
配置指定平台的样式
Ionic 使用 mode 来定义组件的外观。每个平台都有默认的 mode , 任何 mode 下的样式信息,都能被我们覆写。我们可以在 ion-app 中指定mode的值,具体如下:
<ion-app class="md">
覆写 md 模式下的样式
.md button {
text-transform: capitalize;
}
覆写 md 下 Sass 变量的值
$button-md-border-radius: 8px;
// Ionic Sass
// ---------------------------------
@import "ionic";
动态的设置组件的属性
<ion-list [attr.no-lines]="isMD ? '' : null"
EXE – 多主题、多租户构建方案
Ionic 2 团队基于 webpack 开发了项目的构建工具 – ionic-app-scripts
Ionic-app-scripts 的功能很强大,通过它我们可以非常灵活地控制项目构建的每个环节。比如,可以通过 command-line 指定某个环节使用的配置文件:
npm run build --rollup ./config/rollup.config.js
此外,也可以在 package.json 文件中设置配置文件的路径和系统构建参数的值:
"config": {
"t": "sf", // 租户的名称
"l": "zh-cn", // 默认的语言包
"ionic_sass": "./config/sass.config.js", // 自定义Sass构建环节的配置文件
"ionic_copy": "./config/copy.config.js" // 自定义Copy构建环节的配置文件
}
copy.config.js 文件 – 用于配置项目构建过程中文件拷贝的环节:
// copy.config.js 代码片段
module.exports = {
copyResources: {
src: ['{{ROOT}}/materials/' + process.env.npm_package_config_t + '/resources/**/*'],
dest: '{{ROOT}}/resources'
}
}
备注:根目录下的 ‘{{ROOT}}/materials/’ 目录下,用于存放不同租户自定义的资源,如 icon.png 和 splash.png 等图片资源文件。
sass.config.js 文件 – 用于配置项目构建过程中 Sass 编译的环节:
// sass.config.js 代码片段
module.exports = {
variableSassFiles: [
'{{SRC}}/theme/variables.scss',
`{{SRC}}/theme/${process.env.npm_package_config_t}.theme.scss`
]
}
备注:不同租户的主题的命名规则:租户名 + .theme.scss 。项目构建时通过动态设置 process.env.npm_package_config_t 的值,来实现动态构建。
我有话说
1.为什么在 variables.scss 文件中 @import “ionic.globals” 、@import “ionic.ionicons” 能正常导入对应的文件:
在 Scss 文件中导入其他依赖的 *.scss 文件,我们一般使用相对路径的方式。但 variables.scss 导入 ionic.globals 或 ionic.ionicons 文件却不是使用相对路径的方式,此外在我们项目的 src 目录下也没有对应的文件。怎么会那么神奇,刚开始接触的时候,我也一脸懵逼。后面通过深入发掘,终于解开了疑惑。
看完下面的代码,你应该也猜到了答案:
// sass.config.js 代码片段
{
...,
includePaths: [
'node_modules/ionic-angular/themes',
'node_modules/ionicons/dist/scss',
'node_modules/ionic-angular/fonts'
]
}
总结
目前的主题方案,还比较初级,后续还有很多地方需要优化和升级,我们会持续更新相关的内容,有兴趣的小伙伴可以一起探讨哈。