326 - 《手写 styled-components》
发布于 2023年7月26日
之前排查一个问题时把 styled-components 的源码大概翻了一遍,想着既然时间已经花了,就再多花点写个 toy version 记录下吧。
目标是支持最简的 styled-components 使用场景,如下。1)可以用 Tagged Template Literals 声明样式,2)支持 CSS 嵌套语法。
import React from 'react';
import { styled } from '../libs/styled-components';
const Wrapper = styled.div`
font-size: 12px;
h1 {
color: blue;
}
`;
export default function Page() {
return (
<Wrapper>
<h1>Page index</h1>
</Wrapper>
);
}
toy-styled-components 代码如下。
import React from "react";
import * as stylis from "stylis";
function normalizeCSS(css, selector) {
const compiled = stylis.compile(`${selector} {${css}}`);
return stylis.serialize(compiled, stylis.stringify);
}
function insertRules(id, rules) {
const style = document.createElement("style");
style.id = id;
document.head.appendChild(style);
style.innerHTML = rules;
return style;
}
class ComponentStyle {
constructor(rules, componentId) {
this.rules = rules;
this.componentId = componentId;
}
generateAndInjectStyles() {
const name = this.componentId;
const css = this.rules.join("");
insertRules(name, normalizeCSS(css, `.${name}`));
return name;
}
}
function useInjectedStyle(componentStyle