项目背景

公司的产品是一款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,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: "",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'
  ]
}

总结

目前的主题方案,还比较初级,后续还有很多地方需要优化和升级,我们会持续更新相关的内容,有兴趣的小伙伴可以一起探讨哈。

基于 Ionic 2 多主题、多租户构建方案探索的更多相关文章

  1. html5录音功能实战示例

    这篇文章主要介绍了html5录音功能实战示例的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 基于 HTML5 WebGL 实现的医疗物流系统

    物联网( IoT ),简单的理解就是物体之间通过互联网进行链接。这篇文章给大家介绍基于 HTML5 WebGL 实现的医疗物流系统,感兴趣的朋友跟随小编一起看看吧

  3. HTML5页面无缝闪开的问题及解决方案

    这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. HTML5跳转小程序wx-open-launch-weapp的示例代码

    这篇文章主要介绍了HTML5跳转小程序wx-open-launch-weapp的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. Ionic anchorscroll无法在iOS上运行

    我在我的离子应用程序中使用$anchorscroll,在Android上它运行正常但在iOS上我的内容在滚动后卡住了,我无法向上滚动.我尝试使用overflow-scroll=“true”,但这在我的应用程序中都不起作用…有人可以帮我这个吗?

  7. 自定义iOS的应用程序:Cordova / Ionic项目中的didFinishLaunchingWithOptions:方法

    如何在不中断流程的情况下将我的小更改集成到Xcode项目中?

  8. ios – 与Xcode Bots持续集成

    我想使用Xcode机器人进行持续集成.我已经安装了OSXMavericks和Server(版本3).我可以使用Xcode5.0.1创建机器人.在集成时,它正在成功地执行分析测试,但总是最终的集成结果是失败的.IntegrationFailed.Unexpectedinternalservererror.Seetheintegration’slogsformoredetails.`我没有从服务器错误

  9. ios – 使用NSURLSession.downloadTaskWithURL时的内存泄漏

    或者,繁荣,内存泄漏.Apple的NSURLSession类参考在管理边框中的会话部分中指定:IMPORTANT—Thesessionobjectkeepsastrongreferencetothedelegateuntilyourappexitsorexplicitlyinvalidatesthesession.Ifyoudonotinvalidatethesession,yourappleaksmemoryuntilitexits.嗯是的.你也可以考虑这两种方法:>flushWithCompletio

  10. xcode – osx上的config.log是什么?它在哪里?

    任何人都可以解释’configure’是什么和做什么,一般可以找到config.log文件?

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部