Javascript 将css模块应用于AngularJS的更好方法
我现在正在使用带有AngularJS 1.5组件的css模块。堆栈是Javascript 将css模块应用于AngularJS的更好方法,javascript,css,angularjs,css-modules,Javascript,Css,Angularjs,Css Modules,我现在正在使用带有AngularJS 1.5组件的css模块。堆栈是webpack+css加载程序?modules=true+angular 1.5组件+pug 目前,我必须执行以下步骤才能在我的pug模板中使用css模块 // my-component.js import template from 'my-component.pug'; import styles from 'my-component.css'; class MyComponent { constructor($
webpack
+css加载程序?modules=true
+angular 1.5组件
+pug
目前,我必须执行以下步骤才能在我的pug模板中使用css模块
// my-component.js
import template from 'my-component.pug';
import styles from 'my-component.css';
class MyComponent {
constructor($element) {
$element.addClass('myComponent'); // ------ (1)
this.styles = styles; // ------ (2)
}
}
angular.module(name, deps)
.component('my-component', {
controller: MyComponent,
template: template,
});
// my-component.pug
div(class={{ ::$ctrl.styles.fooBar }}) FooBar // ----- (3)
// my-component.css
.myComponent { background: green; }
.fooBar { color: red; }
有两个问题:
$element
,并手动设置其类名。这样做的原因是,AngularJS组件标记本身存在于结果HTML中,没有任何类,这使得CSS很困难。例如,如果我像这样使用上面的MyComponent
:
<div>
<my-component></my-component>
</div>
// my-component.js
angular.module(name, deps)
.component('my-component', {
controller: MyComponent,
template: template,
styles: styles,
});
// my-component.css
div(css-class="fooBar") FooBar
其想法是:
angular.module()在控制器中编写>并应用(1)$element.addClass()
李>
指令css类
将$ctrl.styles
应用于元素
我的问题是,我不知道如何实现上面的想法1(2很容易)。如果有人能分享一些关于这方面的信息,我将不胜感激。我想出了一个我不太满意的解决方案
角度组件可以接受函数作为模板,并使用$element
注入。
如果模板是一个函数,则会向其注入以下局部变量:
- $element-当前元素
- $attrs-元素的当前属性对象
因此,我们可以在模板函数中为component(.myComponent
)附加主类,然后用已编译的类名替换所有出现的类名
// utils.js
function decorateTemplate(template, styles, className) {
return ['$element', $element => {
$element.addClass(styles[className]);
return template.replace(/\$\{(\w+)\}/g, (match, p1) => styles[p1]);
}];
}
// my-component.js
import style from './my-component.css';
import template from './my-component.pug';
import { decorateTemplate } from 'shared/utils';
class MyComponent {
// NO NEED to inject $element in constructor
// constructor($element) { ...
}
angular.module(name, deps)
.component('myComponent', {
// decorate the template with styles
template: decorateTemplate(template, styles, 'myComponent'),
});
// my-component.pug, with special '${className}' notation
div(class="${fooBar}") FooBar
还有一个地方需要改进,decorateTemplate
使用regex替换,模板必须使用特殊的符号${className}
来指定css模块的类名
// utils.js
function decorateTemplate(template, styles, className) {
return ['$element', $element => {
$element.addClass(styles[className]);
return template.replace(/\$\{(\w+)\}/g, (match, p1) => styles[p1]);
}];
}
// my-component.js
import style from './my-component.css';
import template from './my-component.pug';
import { decorateTemplate } from 'shared/utils';
class MyComponent {
// NO NEED to inject $element in constructor
// constructor($element) { ...
}
angular.module(name, deps)
.component('myComponent', {
// decorate the template with styles
template: decorateTemplate(template, styles, 'myComponent'),
});
// my-component.pug, with special '${className}' notation
div(class="${fooBar}") FooBar
欢迎提出任何建议
更新
我更新了我的decorateTemplate()
函数以利用pug特性,这样本地类名就可以写成\u localClassName
// utils.js
function decorateTemplate(template, styles, className) {
return ['$element', ($element) => {
$element.addClass(styles[className]);
return template.replace(/\sclass="(.+?)"/g, (match, p1) => {
let classes = p1.split(/\s+/);
classes = classes.map(className => {
if (className.startsWith('_')) {
let localClassName = className.slice(1);
if (styles[localClassName]) {
return styles[localClassName];
} else {
console.warn(`Warning: local class name ${className} not found`);
return className;
}
} else {
return className;
}
});
return ' class="' + classes.join(' ') + '"';
});
}];
}
// my-component.pug
._fooBar FooBar
尽管这要容易得多,但它并没有消除奇怪的表示法(对于本地类名,以
开头)和regex替换
欢迎提出任何建议