Основы React (10) — Написание стилизованного CSS в React (styled-components)

JavaScript React.js

предисловие

React中编写样式css(styled-components).png

React – это библиотека js для создания пользовательских интерфейсов. Это хорошо видно из уравнения UI=render(). Отображение пользовательского интерфейса зависит от возвращаемого значения функции рендеринга в правой части уравнения.

Когда вы пишете приложение React, вы пишете компоненты React. Наиболее важными данными в компонентах являются реквизиты и состояние. Что касается данных, как их отображать и каким образом — это то, что делает CSS.

В React все может быть Js, то есть css может быть написан на js.По сравнению с традиционным контентом (html), каскадными стилями (css) и действиями (js), это разделение предназначено только для разделения трех разных технологий. физически разделены и управляются отдельно.С другой визуальной точки зрения характеристики высокой сплоченности не достигаются.

Поскольку внешний интерфейс сам по себе является отображением страницы, объединение js и css также является тонкой комбинацией.css также может быть встроен в js в модульной форме, такой как js.

Модули CSS очень хорошо разрешают конфликты стилей и используют концепцию «разделяй и властвуй». В современной разработке компонентов CSS также постоянно развивается. модульность стилей, реализованная в ?

  • Что плохого в том, чтобы определять стили для компонентов через отдельные файлы *.css и указывать их через clssName?

  • Привязка прослушивателя событий в JSX через on*EventType работает только для собственных тегов HTML, если это пользовательский компонент, он не работает, какое хорошее решение?

  • Очарование стилизованных компонентов (функции)

Тогда этот раздел - то, что вы хотите знать

Компоненты в React

Что касается формы определения компонентов в React, то есть следующие способы. Первые два изложены в предыдущем исследовании. Я думаю, вы уже с ними знакомы. Если вы не уверены, вы можете проверить предыдущее содержание.

  • Компонент, объявленный классом class (компонент класса/компонент контейнера)

  • Функционально объявленные компоненты (функциональные компоненты/компоненты без сохранения состояния/компоненты пользовательского интерфейса)

  • стилизованные компоненты

В этом разделе в основном рассказывается о стилях компонентов. Как добавить стили к компоненту React? Давайте посмотрим

Встроенный стиль против внешнего стиля

Чтобы добавить стили к компонентам React, распространенными способами являются

  • Добавьте атрибут стиля, чтобы определить встроенный стиль в JSX.

  • Импортируйте внешние стили с помощью ключевого слова import

Добавьте стили в JSX, как показано ниже: Следующий код объявляет компонент заголовка с компонентом класса класса, этот компонент возвращает кнопку кнопки и добавляет некоторые стили к кнопке через стиль

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>
      </Fragment>
    );
  }
}


const container = document.getElementById('root');

ReactDOM.render(<Header   />, container);

Для приведенного выше встроенного стиля вы также можете определить его как объект Object, чтобы определить стиль, который эквивалентен следующему

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>
    );
  }
}

Хотя это тоже для написания стилей css на JS, управлять им не удобно.Много раз мы используем clssName для определения стилей.По знакомой методике именуем файлы стилей как *.css, а затем импортируем их через import способ представить

import "./style.css";

Для имен стилей иногда имена классов разных компонентов могут совпадать, в этом случае введенные позже имена стилей перезапишут предыдущие, что явно не то, что нам нужно.

Итак, что такое хорошее решение?

В React есть css-in-js, это шаблон, этот css создается с помощью js, а не определяется во внешнем файле, это CSS-модули,В основном это способ создать локальное имя класса с использованием сторонней библиотеки для генерации случайных имен классов.

Для этого css-in-js существует множество сторонних модулей: вы можете получить доступ:GitHub.com/Мишель Эберт…

Сегодняшнее главное исследование — styled-components, у которого наибольшее количество звезд на github.

Преимущество использования styled-components заключается в том, что он позволяет собственному стилю компонента действовать на себя, а не глобально, чтобы они не мешали друг другу.

Сначала вам нужно установить модуль styled-components через npm или cnpm.

npm install -S styed-components

После установки бумага, используемая в styled-components, вводится в модуль путем импорта.

Как показано в следующем коде: введите стилизованные компоненты в верхней части файла, создайте экземпляр стилизованного объекта и используйте строку шаблона в Es6, добавив нужный элемент html под стилизованным объектом, обратными кавычками.

import React, { Fragment, Component } from 'react';
import ReactDOM from 'react-dom';
import styled from "styled-components"; // 引入styled-components库,实例化styled对象

// 声明样式ButtonA组件,通过styled对象进行创建,注意styled.html元素,后面是反引号
const ButtonA = styled.button`
  width: 100px;
  height: 40px;
  border-radius: 3px;
  outline: none;
  border: none;
  cursor: pointer;
  background: #abcdef;
  color: #fff;
`;

// 样式化声明ButtonB组件
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>按钮B</ButtonB>
      </Fragment>
    );
  }
}


const container = document.getElementById('root');

ReactDOM.render(<Header   />, container);

Вот отрендеренный результат:样式化组件.png Уведомление: избегайте объявления стилизованных компонентов в методе рендеринга следующим образом: хотя программа не сообщает об ошибках, это вызовет проблемы с производительностью и приведет к ненужному рендерингу компонентов.

Следующий подход не рекомендуется и его следует избегать

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;
`;

    // 声明样式ButtonB组件,不应该在render函数里面声明样式组件
  const ButtonB = styled(ButtonA)`
      background: red;
`;
    return (
      <Fragment>
        <ButtonA>按钮A</ButtonA>
        <ButtonB>按钮B</ButtonB>
      </Fragment>
    );
  }
}

Поскольку в стиле компонентов в методе рендера каждый создаст новый динамический компонент рендеринга. Это означает, что реагирование должно быть отброшено в каждом последующем рендеринге и пересчитать часть дерева DOM, а не вычисления изменений только разницы между ними. Это может привести к узким местам производительности

Правильный способ - поместить компонент стиля в самую внешнюю часть компонента, как вы делали в начале.

Конечно, чтобы облегчить централизованное управление стилями, для стилизованных компонентов мы часто записываем его в файл, помещаем вышеприведенные стилизованные компоненты в файл style.js, а затем экспортируем через модуляризацию в Es6. внешний мир, если он нужен какому-либо компонентному модулю, его можно импортировать напрямую через import.

import styled from "styled-components"; // 引入styled-components

// 声明样式ButtonA组件
const ButtonA = styled.button`
  width: 100px;
  height: 40px;
  border-radius: 3px;
  outline: none;
  border: none;
  cursor: pointer;
  background: #abcdef;
  color: #fff;
`;

// 声明样式ButtonB组件
const ButtonB = styled.button`
  background: red;
  color: #fff;
  width: 100px;
  height: 40px;
  border-radius: 3px;
  outline: none;
  border: none;
  cursor: pointer;
`;

// 对外暴露出去
export {
    ButtonA,
    ButtonB
}

Внимательные друзья, вы обнаружите, что на самом деле две кнопки имеют много одинаковых стилей, различаются только цвета фона.Если вы пишете много стилей повторно, должно быть много избыточного кода.Возможность наследования предусмотрена в стилизованные компоненты

Чтобы создать новый компонент, наследующий другой стиль,Просто оберните его в стилизованный (унаследованный компонент) конструктор.,Следующим образом

// 声明样式ButtonA组件
const ButtonA = styled.button`
  width: 100px;
  height: 40px;
  border-radius: 3px;
  outline: none;
  border: none;
  cursor: pointer;
  background: #abcdef;
  color: #fff;
`;

// 声明样式ButtonB组件,同时样式ButtonB组件继承了ButtonA组件的样式,又给自身拓展了样式,更改了自身的背景色
const ButtonB = styled(ButtonA)`
  background: red;
`;

Внедрите компоненты ButtonA и ButtonB посредством импорта, где вы хотите использовать компоненты стиля

import React, { Fragment, Component } from 'react';
import ReactDOM from 'react-dom';
import {
  ButtonA,
  ButtonB
}
from './style'



class Header extends Component {
  render(){
    return (
      <Fragment>
          <ButtonA>按钮A</ButtonA>
          <ButtonB>按钮B</ButtonB>  
      </Fragment>
    );
  }
}


const container = document.getElementById('root');

ReactDOM.render(<Header   />, container);

Стилизованные компоненты могут получать реквизиты

Для свойств, определенных вне компонента, его можно получить в компоненте стиля, а некоторые простые логические выражения записываются следующим образом: в компоненте кнопки ОК задается свойство цвета, а в компоненте стиля его можно получить через пропсы

import React, { Fragment, Component } from 'react';
import ReactDOM from 'react-dom';
import {
  Button
}
from './style'

class Header extends Component {

  render() {
    return (
      <Fragment>
        <Button>取消</Button>
        <Button color="red">确定</Button>
      </Fragment>
    );
  }
}


const container = document.getElementById('root');

ReactDOM.render(<Header />, container);

Внутри стилизованного компонентаЗначение атрибута можно указать логически с помощью выражения интерполяции в Es6, ${expression}, для достижения желаемой цели.

import styled from "styled-components"; // 引入styled-components

// 声明样式Button组件
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
}

Результат визуализации показан ниже样式化组件接收参数.pngЭто просто для иллюстрации того, что значения props можно получать внутри стилизованных компонентов, и иногда, в некоторых сценариях, это полезно

Например: некоторые из их собственных сборок пакетов, кнопок и т.п. разных размеров, задав значения атрибутов внешних компонентов, а затем полученные во внутренней сборке стилей, сборка формы управления стилем пользовательского интерфейса

Конечно, эту простую обработку стилей можно выполнить с помощью описанного выше метода наследования.

Примечательно,При вставке фонового изображения прямая вставка не поддерживается, это недействительно

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

Введение локальных изображений должно быть достигнуто путем определения переменных,Следующим образом

import BgImg from './react.jpg'; // 将图片定义成一个变量的方式来引用

const Content = styled.div`
    width: 550px;
    height: 290px;
    background: url(${BgImg}); // 注意这里用Es6中的模板语法
`;

Метод .attrs поддерживает компонент для добавления атрибутов

attrs — это конструктор, который может добавлять свои дополнительные атрибуты к компонентам стиля (этот атрибут допускает только собственные атрибуты тегов html), не поддерживает пользовательские атрибуты, чтобы добавить пользовательские атрибуты, вы можете добавить их только к элементам jsx.

attrs принимает два типа параметров:

  • Параметр может получить объект, а добавленные через него свойства будут объединены в компонент стиля

  • Параметр может быть функцией, если есть значение реквизита, вы можете использовать этот режим, как показано в следующем коде.

import styled from "styled-components"; // 引入styled-components

// 参数是一个对象
const Input = styled.input.attrs({
      placeholder: '请输入信息',
      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
}

где компонент должен быть сослан

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="请输入密码" size='large' type="password" />
      </Fragment>
    );
  }
}


const container = document.getElementById('root');

ReactDOM.render(<Header />, container);

Отрендеренный результат выглядит так:attrs.pngПри наличии параметров компонент стиля можно записать следующим образом, функцию можно получить в attrs, а значения внешних атрибутов можно получить через props

const Input = styled.input.attrs(props => ({ // 参数是一个函数,可以通过props进行接收
    placeholder: '请输入信息',
    type: 'text'
}))`
    width:${props => props.width};
    height: ${props => props.size === 'small'? '24px': '40px'};
    // 如下省略
  `

Уведомление: По поводу приоритета стилей

Встроенный стиль > внешний стиль (компонент стиля), если установлено значение по умолчанию для встроенного элемента, встроенный стиль имеет приоритет

В противном случае атрибуты, установленные внутри атрибутов, переопределяют внешние атрибуты.

Что касается того, когда использовать attrs

Используйте attrs для передачи атрибутов стилизованным компонентам

Используйте attrs, когда вы хотите, чтобы каждый экземпляр стилизованного компонента имел свойство, другими словами, свойства, установленные attrs, которые являются общедоступными, и вы можете передавать реквизиты напрямую, если каждому экземпляру нужен другой экземпляр.

Как переопределить стили по умолчанию

Иногда самый грубый способ переопределить стили — это поставить веса после атрибутов, пас! важно сделать, но это чревато ошибками и проблемами

Конкретная реализацияС помощью амперсанда каждый раз, когда добавляется амперсанд, стиль класса будет генерироваться случайным образом.

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

Как показано ниже如何覆盖默认样式.png

Как переопределить встроенные стили

Встроенные стили имеют наивысший приоритет и всегда имеют приоритет над внешним CSS, поэтому их нельзя переопределить, просто стилизовав компонент, но естьКонкретное решение — использовать &[style] и ! важный способ взвешивания

Иногда, если в JSX объявлен встроенный стиль, но внешняя сторона хочет его переопределить, то на этот разСпособ &[style] и взвешивания импорта очень полезен, но в реальной разработке следует избегать встроенных стилей, здесь просто для иллюстрации таких решений, как

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

Точно так же каждый раз, когда добавляется амперсанд, будет добавлен новый класс.В реальных проектах встроенные стили следует использовать с осторожностью.

сбросить глобальные стили

Для сброса стиля по умолчанию в React используется функция createGlobalStyle, которую необходимо внедрить из styled-components следующим образом:

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;

Вообще говоря, стиль сброса определяется как отдельный файл, вводится в index.js отдельно и действует глобально.

Следует отметить, что способ использования global в более ранних версиях был injectGlobal, и этот API устарел и заменен на createGlobalStyle в styled-components v4.

Стиль написания CSS-модуля

После того, как проект создан с помощью скаффолдинга create-react-app, проект поддерживается css-модулем.

Но необходимо отметить следующие моменты:

  • Имя файла стиля должно быть в форме xxx.module.css или xxx.module.scss: например, styles.module.css или styles.module.scss.

  • Импортируйте файлы стилей в виде переменных, например: импортируйте стили из «./style.module.css», если вы импортируете xxx.css напрямую, имя свойства className в элементе JSX не может импортировать стили через объекты переменных. стиль импортируется напрямую, имя класса может быть напрямую введено в значение атрибута className

  • className добавляется ссылкой на переменную, например: className ={styles.counter}

  • При использовании sass проект, созданный скаффолдингом, по умолчанию поддерживает sass, при его использовании нужно только установить пакет node-sass.

Определите файл styles.module.css в корневой папке и напишите следующие строки кода стиля.

.counter{
    text-align: center;
}

.button{
    padding: 0 10px;
}

.spanText{
    padding: 0 15px;
}

В файл, использующий стиль css-module, импортируйте файл xxx.module.css путем импорта

import React, { Fragment, Component } from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.module.css'; // 引入styles.module.css,实例化一个styles对象

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);

Конкретный эффект заключается в следующем:数字加减成样式组件.gifДля описанного выше метода написания это обычный метод написания, который мы используем в React, но что, если мы используем стилизованные компоненты? как показано в коде ниже

import React, { Fragment, Component } from 'react';
import ReactDOM from 'react-dom';
import styled from "styled-components"; // 引入styled-components

// 在Render函数外定义样式组件
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);

Конечно, как и раньше, вы можете извлекать компоненты стиля отдельно, а затем выставлять их во внешний мир через экспорт, а когда вам нужно их использовать, вы можете импортировать их через импорт в другом файле.

Для именования компонентов стиля: поскольку это компонент, первая буква по соглашению пишется с заглавной буквы, чтобы различать общие элементы тега html.

Небольшой совет: рекомендуемые плагины в vs-code: vscode-styled-components

Подытожим некоторые особенности styled-components

Функции, поддерживаемые стилизованными компонентами

  • Поддержка вложенности, переменных и наследования: вы можете использовать синтаксис, такой как sass и less, для вложения, и вы можете использовать переменные для установки разных стилей. При использовании этих разных стилей вам нужно только передать параметр в стилизованный компонент. Внутри стилизованного компонента вы можете получать внешние через поддерживает значение параметра

  • привязка прослушивателя событий: Для компонентов, оформленных в пользовательском стиле, мониторинг событий может быть привязан. Это проблема, которая решает проблему, заключающуюся в том, что пользовательские компоненты, объявленные классом класса, не могут привязывать мониторинг событий. Тип события onEventType работает только для собственных тегов HTML, а стиль Химические компоненты просто компенсируй это

  • модульный css: вводите код компонента по мере необходимости, избегая избыточного кода.

  • Уникальное имя класса, отсутствие ошибки имени класса, дубликатСтили, сгенерированные :styled-components, генерируют уникальные имена классов. Никогда не беспокойтесь о повторениях, наложениях или орфографических ошибках

  • Легче удалять стили, легко поддерживать: все написанные стили связаны с определенным компонентом. Если компонент не используется (инструмент может его обнаружить) и удаляется, все стили будут удалены, сохраняя единство функциональности, обеспечивая высокую связность, низкое связывание компонентов.

  • Динамические стили: компонент стиля может получать параметры, очень просто настроить и расширить стиль компонента, без необходимости создавать множество классов для поддержания стиля компонента.

Суммировать

Эта статья в основном объясняет стиль написания React, это не высокоуровневый контент, это более простой

Не обязательно писать стилизованные компоненты через внедрение сторонней библиотеки styled-components, это зависит от команды проектной компании, если вы этим не пользуетесь, то также возможно писать стили React через css-модуль.

Конечно, если используются styled-components, это решит некоторые проблемы, такие как переопределение стилей, именование и другие болевые точки, а также решит проблему невозможности привязки событий к пользовательским компонентам в компонентах объявления класса.

Эта статья только что познакомила вас с некоторыми общими знаниями о styled-components, а для более подробного использования styled-components: вы можете обратиться к официальной документации styled-components.