preface

React is a js library for building user interfaces, which are nicely mapped from the UI=render() equation, which displays the UI depending on the render function on the right side of the equation.

Write the React component. The most important data in the React component is props and state. How to display the data is CSS

In React, everything can be Js, that is to say, CSS can be written in Js. Compared with the traditional content (HTML), cascading style (CSS), and behavior action (Js), this separation only separates the three different technologies physically and manages them separately. From another visual point of view, it is not practical It is characterized by high cohesion

Since the front end itself is the display of the page, so js and CSS together, is also a fine-grained combination, CSS can also be the same as JS, through the form of modular embedded into JS

CSS modules solve style conflicts and make use of the concept of divide and conquer. Nowadays, component-based development is popular, and CSS is constantly evolving. Just like JS, there are also variables and functions with the same vitality as JS.

  • What’s wrong with styling components in a separate *.css file and specifying them by clssName?

  • Listener bindings on JSX, via on*EventType, only work with native HTML tags, but not with custom components. What’s the solution?

  • The charm of styling components (features)

Then this is what you want to know

React component form

There are several ways to define components in React, the first two of which are familiar to you. If you are not sure, you can check the previous content

  • Components declared by class class (class components/container components)

  • Functionally declared components (function components/stateless components /UI components)

  • Styled Components (Styled Components)

This section is about styling components. How to style a React component? Let’s take a look

Inline style vs. external style

Here are some common ways to style the React component

  • Add the Style attribute on JSX to define inline styles

  • Introduce external styles through the import keyword

Add styles on JSX as shown below: The following code declares a Header component with the class component, which returns a button button and styles the button with style

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; class Header extends Component { render(){ return ( <Fragment> <button style = {{ width: '100px', height: '40px', borderRadius: '3px', outline: 'none', outline: 'none', border: 'none', cursor: 'pointer', background: '# abcdef, color:' # FFF '}} > button button < / button > < / fragments >); } } const container = document.getElementById('root'); ReactDOM.render(<Header />, container);Copy the code

For the inline style above, it is possible to define the style as an Object, which is equivalent to the following

class Header extends Component { render(){ const btnStyle = { width: '100px', height: '40px', borderRadius: '3px', outline: 'none', border: 'none', cursor: 'pointer', background: '#abcdef', color: '# FFF '} return (<Fragment> <button style = {btnStyle}>button </button> </Fragment>); }}Copy the code

Although this is also to write CSS styles in JS, but it is not convenient to manage, most of the time, we use clssName to define styles, according to the familiar way, is to name the style file *.css, and then import the way to import

import "./style.css";
Copy the code

For style names, sometimes the className may be the same for different components, in which case the style name introduced later overrides the previous one, which is obviously not the desired result

What’s a good solution?

In React, there’s CSS-in-JS, which is a pattern. The CSS is generated by JS rather than defined in an external file. It’s CSS Modules, which is a way to create local class names using the way third-party libraries generate random class names

There are many third party modules for csS-in-JS: visit :github.com/MicheleBert…

Styled Components, the most popular star on Github

The advantage of using styled- Components is that it allows the components’ own styles to operate for themselves, not globally, so that they do not interfere with each other

First, you will have to install the Styled – Components module via NPM or CNPM

npm install -S styed-components
Copy the code

After installation, the module is introduced as import in a file using Styled – Components

As shown in the following code: Instantiate a Styled object by introducing styled components at the top of the file, taking advantage of a template string in Es6, the back quotes, by adding the DESIRED HTML elements to the Styled object

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; import styled from "styled-components"; // Introduce the Styled - Components library, instantiate the Styled object // declare the style ButtonA component, and create from the Styled object. Note the styled. HTML element, followed by the backquote const ButtonA = styled.button` width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; background: #abcdef; color: #fff; `; // Styled ButtonB module const ButtonB = Styled. Button 'background: red; color: #fff; width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; `; Class Header extends Component {render(){return (<Fragment> <ButtonA> A</ButtonA> <ButtonB> </ButtonB> </ButtonB> </Fragment> ); } } const container = document.getElementById('root'); ReactDOM.render(<Header />, container);Copy the code

Here is the render result: Pay attention toAvoid declaring styling components in the Render method as shown below: while this does not generate an error, it can cause performance problems and cause components to render unnecessarily

The following is not recommended and should be avoided

class Header extends Component { render() { const ButtonA = styled.button` width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; background: #abcdef; color: #fff; `; Const ButtonB = Styled (ButtonA) 'background: red; `; Return (<Fragment> <ButtonA> A</ButtonA> <ButtonB> B</ButtonB> </Fragment>); }}Copy the code

Because the styling component is declared in the Render method, a new component is dynamically rendered each time. This means React must discard and recalculate that part of the DOM tree with each subsequent render, rather than just counting the difference between them as they change. This can lead to performance bottlenecks

The right thing to do is to put the style component on the outside of the component as you did in the beginning

Of course, in order to facilitate the centralized management of style, for the styling components, we often write it in a file, put the above style components in a style.js file, and then exposed through the modular export in Es6, as long as any component module needs, directly through the import can be imported

import styled from "styled-components"; // Styled - Components // style ButtonA component const ButtonA = styled. Button 'width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; background: #abcdef; color: #fff; `; // Styled ButtonB module const ButtonB = Styled. Button 'background: red; color: #fff; width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; `; Export {ButtonA, ButtonB}Copy the code

For styled components, there will be a lot of redundant code. Styled components provide the ability to inherit

To create a new component that inherits another style, simply wrap it in the Styled (inherited component) constructor, as shown below

// Styled ButtonA component const ButtonA = Styled. Button 'width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; background: #abcdef; color: #fff; `; Const ButtonB = Styled (ButtonA) 'background: red; // Styled ButtonB extends the style of ButtonA, and changes its background color. `;Copy the code

Import the ButtonA,ButtonB component where you want to use the style component

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; import { ButtonA, ButtonB} from './style' class Header extends Component {render(){return (<Fragment> <ButtonA> <ButtonB> </ButtonB> </Fragment>); } } const container = document.getElementById('root'); ReactDOM.render(<Header />, container);Copy the code

The style component can receive props

For properties defined outside of the component, it is possible to receive them in the style component by writing some simple logical expressions as follows: Set a color property in the Sure button component, and receive them in the style component via props

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; Import {Button} from './style' class Header extends Component {render() {return (<Fragment> <Button> <Button color="red"> </Button> </Fragment>); } } const container = document.getElementById('root'); ReactDOM.render(<Header />, container);Copy the code

In the style component, attribute values can be used to specify logical judgments in the form of interpolation,${expression} in Es6, to achieve their desired purpose

import styled from "styled-components"; // Styled - Components // Style element const Button = styled. Button 'width: 100px; height: 40px; border-radius: 3px; outline: none; border: none; cursor: pointer; background: ${props => props.color ? "red": '#fff'}; color: ${(props) => props.color ? '#fff': 'red'}; border: 2px solid red; margin-right: 15px; `; Export {Button} export {Button}Copy the code

The rendered result is shown belowThis is just to show that it is possible to receive props values inside a styling component, which is sometimes useful in some scenarios

For example: encapsulate some of their own components, different size buttons and so on, by setting property values outside the component, and then receive in the style component, control the style UI form of the component

Of course, this kind of simple style processing, can be handled with the above inheritance

It is important to note that when inserting a background image, there is no support for direct insertion, which will not work

const Content = styled.div`
    width: 550px;
    height: 290px;
    background:url('./react.jpg');
`;
Copy the code

Importing local images must be done by defining variables, as shown below

import BgImg from './react.jpg'; // Reference the image as a variable const Content = styled. Div 'width: 550px; height: 290px; background: url(${BgImg}); // Note that Es6 template syntax 'is used here;Copy the code

The.attrs method supports adding attributes to components

Attrs is a constructor that adds its own additional attributes to a style component (this attribute only allows attributes that are native to HTML tags). Custom attributes are not supported, and can only be added on JSX elements

Attrs accepts two types of arguments:

  • The parameter can receive an object with attributes added to it that will be incorporated into the style component

  • The parameter can be a function, and if it has props, the pattern can be used as shown in the code below

import styled from "styled-components"; Style.input. Attrs ({placeholder: 'Please Input information ', type: 'text' })` width:${props => props.width}; height: ${props => props.size === 'small'? '24px': '40px'}; font-size: 14px; text-indent: 10px; border-radius: 3px; border: 1px solid palevioletred; display: block; margin: 0 0 1em; ::placeholder { color: palevioletred; } '// export {Input}Copy the code

At the component to reference

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; import { Input } from './style' class Header extends Component { render() { return ( <Fragment> <Input width="150px" Placeholder =" size="small"/> <Input width="200px" placeholder=" password" /> </Fragment> ); } } const container = document.getElementById('root'); ReactDOM.render(<Header />, container);Copy the code

The render result looks like this:The style component can be written as follows if there are parameters,attrs accepts a function, and props accepts external property values

Style.input. Attrs (props => ({// Const Input = style.input. 'text' }))` width:${props => props.width}; height: ${props => props.size === 'small'? '24px': '40px'}; // omit 'as followsCopy the code

Note: Regarding style priority

Inline style > External Style (style component), if the inline element is set to a default value, inline style takes precedence

Otherwise, attributes set in attrs override external attributes

As for when to use attrs

Use attrs to pass attributes to the styling component

Use attrs when you want to style each instance of the component with that prop. In other words, the attribute set by attrs, which is public, can be passed directly if each instance needs a different instance

How do I override the default styles

Sometimes the crudest way to overwrite a style is to put weight after an attribute, pass! Important to do, but this is very error-prone, and very problematic

This is done in the form of ampersand, which generates a random class style for each additional ampersand

const ButtonB = styled(ButtonA)`
  &&& {
    color: palevioletred;
    font-weight: bold;
  }
`
Copy the code

As shown in the figure below

How do I override inline styles

Inline styles have the highest priority, always taking precedence over external CSS, so there is no way to override it by simply styling components, but there is a specific workaround using &[style] and! Important Indicates the weight method

The &[style] and import weights can be useful in cases where inline styles are declared on JSX but the outside world wants to override them, but inline styles should be avoided in real development, just to illustrate such solutions

const ButtonB = styled(ButtonA)` &[style]{ background: blue ! important; font-weight: bold; } `;Copy the code

Similarly, each additional ampersand, will add a new class, in the actual project, should use less in-line style, do not temporarily cool, after digging their own pits

Resetting global styles

For resetting the default style in React, it uses the createGlobalStyle function, which needs to be injected from the Styled components as follows:

import { createGlobalStyle } from 'styled-components'

const globalStyle = createGlobalStyle`
   html, body, div, span, applet, object, iframe,
        h1, h2, h3, h4, h5, h6, p, blockquote, pre,
        a, abbr, acronym, address, big, cite, code,
        del, dfn, em, img, ins, kbd, q, s, samp,
        small, strike, strong, sub, sup, tt, var,
        b, u, i, center,
        dl, dt, dd, ol, ul, li,
        fieldset, form, label, legend,
        table, caption, tbody, tfoot, thead, tr, th, td,
        article, aside, canvas, details, embed,
        figure, figcaption, footer, header, hgroup,
        menu, nav, output, ruby, section, summary,
        time, mark, audio, video {
            margin: 0;
            padding: 0;
            border: 0;
            font-size: 100%;
            font: inherit;
            vertical-align: baseline;
        }
        article, aside, details, figcaption, figure,
        footer, header, hgroup, menu, nav, section {
            display: block;
        }
        body {
            line-height: 1;
        }
        ol, ul {
            list-style: none;
        }
        blockquote, q {
            quotes: none;
        }
        blockquote:before, blockquote:after,
        q:before, q:after {
            content: '';
            content: none;
        }
        table {
            border-collapse: collapse;
            border-spacing: 0;
        }

        body {
            margin: 0;
            padding: 0;
            font-family: sans-serif;
        }

`
export default globalStyle;
Copy the code

In general, the resetting style is defined as a single file, which is introduced separately in index.js, and applies globally

Note that injectGlobal was used in earlier versions, and this API has been deprecated and replaced by createGlobalStyle in Styled – Components V4

Css-module writes styles

After a project is created using the create-React-app scaffolding, it supports CSS-Module

However, the following points should be noted:

  • The name of the style file must be either xxx.module. CSS or xxx.module. SCSS: for example, styles.module. CSS or styles.module

  • Import a style file as a variable, for example :import styles from ‘./style.module. CSS ‘, if you import xxx. CSS directly, you cannot import the style of the property name of the className on the JSX element through the variable object

  • ClassName is added as a variable reference, for example :className ={styles.counter}

  • When using sass, scaffolds create projects that support Sass by default, so simply install the Node-sass package

Define styles.module. CSS in the root folder and write the following lines of style code

.counter{
    text-align: center;
}

.button{
    padding: 0 10px;
}

.spanText{
    padding: 0 15px;
}
Copy the code

In a csS-module style file, import the xxx.module. CSS file as an import

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; import styles from './styles.module.css'; Class Counter extends Component {constructor(props){super(props); this.state = { count: 0 } } increment = () => this.setState({ count: this.state.count + 1 }) decrement = () => this.setState({ count: this.state.count - 1 }) render() { return ( <Fragment> <div className={styles.counter}> <button className={styles.button} onClick={this.decrement}> - </button> <span className={styles.spanText}>{this.state.count}</span> <button className={styles.button} onClick={this.increment}> + </button> </div> </Fragment> ) } } const container = document.getElementById('root'); ReactDOM.render(<Counter />, container);Copy the code

The specific effect is as follows:For the style described above, this is the style we will use in React, but what if it is styled-components? See the code below

import React, { Fragment, Component } from 'react'; import ReactDOM from 'react-dom'; import styled from "styled-components"; Const CounterWrap = styled. Div 'text-align: center; ` const SpanText = styled.span` padding: 0 15px; ` const Button = styled.button` padding: 0 10px; ` class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 } } increment = () => this.setState({ count: this.state.count + 1 }) decrement = () => this.setState({ count: this.state.count - 1 }) render() { return ( <Fragment> <CounterWrap> <Button onClick={this.decrement}>-</Button> <SpanText>{this.state.count}</SpanText> <Button onClick={this.increment}>+</Button> </CounterWrap> </Fragment> ) } } const container = document.getElementById('root'); ReactDOM.render(<Counter />, container);Copy the code

Of course, you can pull out the style components as before, and then expose them by export, and import them in another file when needed

The naming of style components: components are capitalized by convention to distinguish normal HTML tag elements

In VS-Code, the recommended plugin is vscode-styled- Components

The following summarizes some features of the Styled – Components

Styled – Components Specifies the supported features

  • Support for nesting, variables, and inheritance: you can use syntax like SASS,less, and you can use variables to set different styles. Using these different styles, you only need to pass a parameter to the styling component. Inside the styling component, you can use props to receive external parameter values

  • Event-listening binding: Event-listening binding can be done for custom styled components. This is the pain point of resolving the problem of custom components declared by class. The onEventType event type only works for native HTML tags, but the styled component compensates for this

  • Modular CSS: Introduce component code on demand, avoiding some redundant code

  • Styled – Components Unique class name, no class name error, repeat: Styled – Components Generates a unique class name. Never worry about repetition, overlap or spelling mistakes

  • Easier to remove styles, easy to maintain: Written styles are associated with a particular component, and if the component is not used (which the tool can detect) and removed, all styles are removed, keeping functionality single and achieving high cohesion, low coupling and componentalization

  • Dynamic styling: Stylesheet components can take parameters, making it easy to adjust and extend the styling of components without having to create multiple class classes to maintain the styling of components

conclusion

React postures React postures React postures

Styled components are not required, depending on the project team, via the introduction of the Gravitation-Components third-party library. Instead, it is possible to style React using csS-Module

Of course, using styled Components solves some problems, such as style overwriting, naming pain points, and the inability to bind events to custom components in class-declared components

For styled Components, please refer to the official documentation for styled Components