设计思路
为什么要设计一个CSS控制器?主要有以下几个原因:1、不想直接使用style操作元素的样式;2、不喜欢CSS/JS/TS文件分离;3、可以通过前端框架的高级功能(例如Vue的指令)执行一些更便捷的操作。
基于第三个原因举个简单的例子:例如在Vue中通过指令实现一个v-style指令,通过v-style="background: red"这样的方式直接帮你在元素上绑定一个匿名的class,你不用在意样式表的类名是如何取的,系统会帮你自动为元素绑定上类名,因此元素上也不会出现一个style属性。
基于此,你甚至可以通过你自己的加密算法将CSS样式加密,任何不熟悉你页面构造的人,将无法直接获取你的页面样式及结构。
设计实现
以下展示基本实现
class StyleControl {
static styleElement: StyleControl | null
private readonly styleElement: HTMLStyleElement
constructor() {
const styleElement = document.createElement("style");
document.head.appendChild(styleElement);
this.styleElement = styleElement;
}
static style(): StyleControl {
if (this.styleElement) {
return this.styleElement
}
this.styleElement = new StyleControl();
return this.styleElement
}
private rulesMap(style: Record<string, string | number>) {
const rules: string[] = []
for (const [key, value] of Object.entries(style)) {
rules.push(`${key}: ${value}`);
}
return rules;
}
insert(selector: string, style: Record<string, string | number> | string): number | void {
let rules: string[] = []
const sheet = this.styleElement.sheet;
if (sheet) {
if (typeof style === 'string') {
rules.push(style);
} else {
rules = this.rulesMap(style)
}
return sheet.insertRule(`${selector} { ${rules.join(";")} }`, sheet.cssRules.length);
}
}
insertKeyframes(selector: string, keyframes: Record<string, Record<string, string | number>>) {
const rules: string[] = []
const sheet = this.styleElement.sheet;
if (sheet) {
for (const [key, value] of Object.entries(keyframes)) {
rules.push(key, `{ ${this.rulesMap(value).join(';')} }`)
}
return sheet.insertRule(`${selector} { ${rules.join(" ")} }`, sheet.cssRules.length);
}
}
delete(index: number): void {
const sheet = this.styleElement.sheet;
if (sheet) {
return sheet.deleteRule(index);
}
}
}
export default StyleControl;
DISCUSSION
评论
还没有公开评论,欢迎留下想法。