Angular 4 CLI,WebPack,为整个网站动态切换引导主题
Posted
技术标签:
【中文标题】Angular 4 CLI,WebPack,为整个网站动态切换引导主题【英文标题】:Angular 4 CLI, WebPack, switching bootstrap theme dynamically for the entire website 【发布时间】:2017-11-26 02:23:44 【问题描述】:我想为用户提供一个按钮来改变整个网站的主题。我对所有内容都使用引导程序“.scss”文件。 这是我所做的:
我在“src/styles”文件夹中有“dark-styles.scss”和“light-styles.scss”。这两个文件都覆盖了我需要覆盖的类和方法,并且还从“node-module”导入了“bootstrap.scss”作为默认值。当我通过“.angular-cli.json”向应用程序提供任何这些文件时,如下所示;它完美地工作。
"styles": [
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/@swimlane/ngx-datatable/release/index.css",
"../node_modules/@swimlane/ngx-datatable/release/assets/icons.css",
"../src/styles/dark-styles.scss"
],
或者,
"styles": [
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/@swimlane/ngx-datatable/release/index.css",
"../node_modules/@swimlane/ngx-datatable/release/assets/icons.css",
"../src/styles/light-styles.scss"
],
如果我提供黑暗,主题就是黑暗,如果我提供光明,主题就是光明。
但我想要实现的是动态地允许用户更改主题。因此,基于***中的其他答案;我访问了我的应用程序组件中的“文档”,这也是我的根组件。它使我可以访问整个 html 页面,其中我有一个可以从 app-component 设置的链接标签。
HTML 文件
<head>
<link id="theme" type="text/scss" rel="stylesheet" src="">
</head>
<body>
content .....
</body>
Angular-cli.json
"styles": [
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/@swimlane/ngx-datatable/release/index.css",
"../node_modules/@swimlane/ngx-datatable/release/assets/icons.css"
],
应用组件:
import Component, OnInit, Inject from '@angular/core';
import DOCUMENT from '@angular/platform-browser';
@Component(
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
)
export class AppComponent implements OnInit
currentTheme: string;
constructor( @Inject(DOCUMENT) private document)
ngOnInit()
this.currentTheme = 'dark';
this.document.getElementById('theme').href = '../styles/dark-styles.scss';
handelChangeTheme(event)
if (this.currentTheme === 'dark')
this.document.getElementById('theme').href = '../styles/light-styles.scss';
this.currentTheme = 'light';
console.log('light');
else
this.document.getElementById('theme').href = '../styles/dark-styles.scss';
this.currentTheme = 'dark';
console.log('dark');
在触发事件“handleChangeTheme”时,html 文件中#theme 的 href 更改。但它不会更新或应用样式。我知道它与 WebPack 以及它编译 scss 文件的方式有关。有没有人遇到过类似的情况或知道这个问题的解决方案。谢谢
【问题讨论】:
我猜你必须编译两个 scss 文件并让它们可供应用程序选择(即将它们打包到你的 webapp 中) @ochi ...也尝试过...没有用。这样做时,将应用默认引导程序,覆盖全部被拒绝。 你解决了吗?我被指派做同样的事情。任何帮助将不胜感激 不,我暂时把它放在一边......在材料中实现这一点很容易 Webpack 使用处理器来转换 Sass -> CSS。假设路径和文件类型正确,这似乎与 Material doc 使用的技术相同(右上角的油漆桶,选择主题更新 href 为link.style-manager-theme
:material.angular.io)
【参考方案1】:
我刚刚在本地完成了您的示例,在我将其更改为 text/css
后,type="text/scss"
似乎有问题,它开始工作。我首先认为您需要重新创建元素,但问题似乎与类型有关
由于它的主题,我建议您使用这些文件的编译 css 版本,将它们放入 assets
文件夹中,angular-cli 会将它们复制到 serve
和 build
此外,当您在 Angular 中引用 scss 时,它会使用 webpack 编译为 css。
【讨论】:
我开始悬赏这个问题,因为我遇到了同样的问题。我结束了使用另一种方法解决它,更准确地说,类似于:sitepoint.com/sass-theming-neverending-story @MarcusVinicius - 对您的方法进行更详细的解释会有所帮助。您是否将 scss 预编译为 css(如 Volodymyr Bilyachat 所建议的那样) - 这是使用 angular-cli 本身发生的,还是您必须添加一些手动 node-sass 命令才能使 htis 工作......以及您是如何切换主题的(使用链接?正如 Virodh 最初提出的那样?) @RafiAliKhan,我添加了一个答案,更详细地解释了我如何设法使动态主题工作。【参考方案2】:我通过使用以下方法设法让动态主题在 Angular 4 + Bootstrap 中工作:
使用地图定义主题颜色:
$themes: (
alpha: (
primary: #2b343e,
info: #3589c7,
top-color: #000000,
top-font-color: #ffffff,
...
),
beta: (
primary: #d2a444,
info: #d2a444,
top-color: #ffffff,
top-font-color: #000000,
...
)
)
然后,创建以下 mixin 来为每个主题名称和给定属性输出颜色:
@mixin theme($property, $key, $themes: $themes)
@each $theme, $colors in $themes
&.theme-#$theme,
.theme-#$theme &
#$property: map-get($colors, $key);
我使用 mixins 来控制单个属性:
@mixin color($arguments...)
@include themify('color', $arguments...);
@mixin background-color($arguments...)
@include themify('background-color', $arguments...);
对于每个“主题化”组件,我在声明属性时必须使用上面的 mixins:
.page-top
@include background-color('top-color');
@include color('top-font-color');
height: 66px;
width: 100%;
...
CSS 输出类似于:
.page-top
height: 66px;
width: 100%;
...
.page-top.theme-alpha,
.theme-alpha .page-top
background-color: #000000;
color: #ffffff;
.page-top.theme-beta,
.theme-beta .page-top
background-color: #ffffff;
color: #000000;
最后,要使主题可用,您必须在某些父组件中控制主题类:
<!-- class="theme-alpha" -->
<main themeChange>
<page-top></page-top>
<sidebar></sidebar>
<page-bottom></page-bottom>
</main>
themeChange
指令可以这样写:
@Directive(
selector: '[themeChange]'
)
export class ThemeChange implements OnInit
@HostBinding('class') classes: string;
private _classes: string[] = [];
ngOnInit()
// grab the theme name from some config, variable or user input
this.classesString = myConfig.theme;
【讨论】:
【参考方案3】:经过几个小时的尝试,我终于让 bootstrap 主题切换器 工作了。这是我的解决方案:
-
不要使用 bootswatch.scss,而是下载每个主题的编译版本,将它们放在同一个资产文件夹中并相应地重命名文件。
将此行添加到 index.html。选择默认主题:
< link id="theme" type="text/css" rel="stylesheet" href="/assets/css/theme_slate_bootstrap.min.css">
...
...
<body class="theme-slate">
...
3.目前在app.component中设置了切换主题的快捷方式。所以这是 app.component.ts
import Component, OnInit, Renderer2, Inject from '@angular/core';
import DOCUMENT from '@angular/platform-browser';
@Component(
selector: 'apps',
templateUrl: './app.component.html'
)
export class AppComponent implements OnInit, OnDestroy
private currentTheme: string = 'slate';
constructor(private renderer: Renderer2, @Inject(DOCUMENT) private document)
ngOnInit()
theme(type)
this.renderer.removeClass(document.body, 'theme-'+this.currentTheme);
this.currentTheme = type;
this.renderer.addClass(document.body, 'theme-'+this.currentTheme);
this.document.getElementById('theme').href = '/assets/css/theme_'+type+'_bootstrap.min.css';
主题切换按钮
<div style="display:block; position: absolute; top:0; right:0; text-align:right; z-index:100000;">
<button class="btn btn-primary btn-sm" (click)="theme('slate')">Slate</button>
<button class="btn btn-secondary btn-sm" (click)="theme('yeti')">Yeti</button>
<button class="btn btn-secondary btn-sm" (click)="theme('darkly')">Darkly</button>
</div>
在 angular.json 中添加这个自定义文件
"styles": [
"src/assets/scss/custom.scss"
],
custom.scss - 添加您的自定义代码以在此处工作
$themes: (
slate: (
name: 'slate',
primary: #3A3F44,
secondary: #7A8288,
...
),
yeti: (
name: 'yeti',
primary: #008cba,
secondary: #eee,
...
),
darkly: (
name: 'darkly',
primary: #008cba,
secondary: #eee,
...
),
);
/*
* Implementation of themes
*/
@mixin themify($themes)
@each $theme, $map in $themes
.theme-#$theme &
$theme-map: () !global;
@each $key, $submap in $map
$value: map-get(map-get($themes, $theme), '#$key');
$theme-map: map-merge($theme-map, ($key: $value)) !global;
@content;
$theme-map: null !global;
@function themed($key)
@return map-get($theme-map, $key);
*
@include themify($themes)
// custom theme to your needs. Add here
@if themed('name') == 'slate'
@if themed('name') == 'yeti'
@if themed('name') == 'darkly'
// Below will effect all themes
.btn, .form-control, .dropdown, .dropdown-menu
border-radius: 0;
// This is just example to code. When switching theme, primary button theme should changed. Below code is not required.
.btn-primary
background-color: themed('primary');
border-color: themed('primary');
// ***********************************************************************
@import "custom-additional-classes";
希望这对寻求引导主题切换器解决方案的每个人都有帮助
【讨论】:
以上是关于Angular 4 CLI,WebPack,为整个网站动态切换引导主题的主要内容,如果未能解决你的问题,请参考以下文章
使用 @ngtools/webpack 在 Angular 11 + Webpack 4 中实现 AOT
带有primeng 404问题的angular-cli@webpack
在 angular-cli@webpack 中使用 socket.io-client
Angular-cli.json 、 webpack.conf 和 tsconfig.json 之间的区别