What is styled – components
Styled – components website
Styled – Components is a CSS in JS scheme
advantage
- Easy to set dynamic styles
- Styled – Components The generated className is unique, and there is no need to worry about className conflicts
- Easy to use, no need to configure Webpack, out of the box
- Dealing with CSS Modules variables is tricky for the SSR class framework, so styled- Components is used for the scheme
Simple and easy to implement
For the Style network, let’s implement a V-Styled style. The following implementation and source discrepancy, a lot of simplification
Simple usage
Styled – Components are used as follows:
const Div = styled.div`
border: 1px solid red;
font-size: ${(props) => (props.fs ? props.fs : '20px')};
color: red;
border-radius: ${(props) => (props.radius ? props.radius : ' ')};
`;
function App() {
return (
<Div fs='30px' radius='10px'>
Hello world
</Div>
);
}
Copy the code
As you can see from above, styled- Components uses a labeled template string. Styled (‘div’), and styled(‘div’) returns a tag template string function
First, let’s declare a function v
function v(tag) {}
Copy the code
For our V-Styled also to support multiple HTML tags, the following transformation is required:
let domElement = ['a'.'span'. ] ; domElements.forEach((domElement) = > {
v[domElement] = v(domElement);
});
Copy the code
V (‘div’) returns a tag template string function to modify the implementation of function v
function v(tag) {
return (strings: any[], ... args: any) = > {};
}
Copy the code
Step 1: Work with the CSS content
A tagged template string whose first argument is a strings array and the remaining arguments are related to the expression ${expression}
First, we declare a DIV component
// Declare a Div component
const Div = v.div`
border: 1px solid red;
font-size: ${(props) => (props.fs ? props.fs : '20px')};
color: red;
border-radius: ${(props) => (props.radius ? props.radius : ' ')};
`;
const APP = () = >{
/ / use
return <Div fs="12px" radius="4px">
}
Copy the code
So if we do nothing, the function v prints:
function v(tag) {
return (strings: any[], ... args: any) = > {
/** The first parameter strings is: [" border: 1px solid red; font-size: ", "; color: red; border-radius: ", "; "] ƒ (
console.log(strings, args);
};
}
Copy the code
Once we have the parameters passed by the template string, we need to process it by executing the passed expression and then putting it back in its original position. We want to generate CSS rules like this:
{
border: 1px solid red;
font-size: 12px;
color: red;
border-radius: 4px;
}
Copy the code
${(props) => (props. Fs? Fs: ‘props ‘)}, ${(props) => (props. Radius: ”)} we need to mix the first argument, strings, with the rest of the parameters, and write an exchange function:
const interleave = (strings, interpolations) = > {
const result = [strings[0]].for (let i = 0, len = interpolations.length; i < len; i += 1) {
result.push(interpolations[i], strings[i + 1]);
}
return result;
};
Copy the code
Now we can mix the parameters and the result is:
function v(tag) {
return (strings: any[], ... args: any) = > {
const cssRules = interleave(strings, args);
/ * * parameters as output: [" border: 1 px solid red; the font - size: ", ƒ (), "; color: red; border - the radius: ", ƒ (), "; "] * * /
console.log(cssRules);
};
}
Copy the code
All that is left to do is to execute the output of the expression passed in, and then concatenate the array into a string to generate the corresponding CSS rules. For ease of use later, we call the result of the mix cssRules
Step 2: Generate the React Element
Because we need to support multiple DOM tags, we use React. CreateElement to create the domElement
function styledComponentImpl() {
return React.createElement('div', { className: 'test' });
}
Copy the code
We call styledComponentImpl() to create a div tag with className test
Back to our function v, we need to pass the cssRules, tag, and className information to styledComponentImpl. It’s very simple. Tags, rules and other information are passed to a StyledComponentL using the WrappedStyledComponent object.
function v(tag: string) {
return (strings: any[], ... args: any) = > {
const cssRules = interleave(strings, args);
let WrappedStyledComponent: any;
// Declare a function component
const forwardRef = (props: any, ref: any) = >
styledComponentImpl(WrappedStyledComponent, props, ref);
WrappedStyledComponent = React.forwardRef(forwardRef);
WrappedStyledComponent.tag = tag;
WrappedStyledComponent.rules = rules;
// simply generate a non-repeating className
WrappedStyledComponent.className = `v-${uuidv4()}`;
return WrappedStyledComponent;
};
}
Copy the code
After obtaining cssRules,className, and Tag, you can evaluate styles, insert styles, and return the React Element in response. StyledComponentImpl implements the following:
// Create react Element
function styledComponentImpl(
forwardedComponent: IStyledComponent,
props: Object,
forwardedRef: Ref<any>,
) {
const{ children, ... restProps } = props;// Get cssRules, className, tag
const{cssRules, className, tag} = forwardedComponent;// Here we pass props to an expression in the template string to execute
const css = cssRules
.map((r: any) = > (typeof r === "function" ? r(restProps) : r))
.join("");
// Generate the style and insert the style into the head
const injectedCSS = `.${className} { ${css}} `;
insertCss(injectedCSS);
// Return the React Element with the className
return React.createElement(tag, { className }, children);
}
Copy the code
Step 3: Insert styles into head
Get the styleSheet instance, and then call its insertRule method to insert the style, as shown in the following example:
// Insert CSS into head
function insertCss(css: string, index = 0) {
const { styleSheets } = document;
styleSheets[0].insertRule(css, index);
}
Copy the code
talk is cheap , show you the code
Author reference styled- Components source code simple implementation, implementation address
Styled – the components of the problem
Frequent changes in props generate a lot of redundant styles
Each time a new props is passed in, a new className is generated, resulting in a lot of redundant styles. Therefore, if the props of the style component change frequently, it is recommended to use inline style directly. Repetition demo
other
Styled components uses monorepo to manage the code, and after starting the example in the sandbox directory yarn Start, we go to the styled components source directory, and after making changes, sandbox will listen for file changes. The Styled – Components code will be rebuilt. The local debugging experience is excellent