Strong opinions are very useful to others.
Those who were undecided or ambivalent can just adopt your stance.
But those who disagree can solidify their stance by arguing against yours
Четкая точка зрения очень полезна. Свингеры могут принять вашу точку зрения, не беспокоясь. Несогласные могут укрепить свое мнение путем обсуждения.
----Derek Sivers
предисловие
Я должен признать, что CSS-решение Vue очень естественное и лаконичное, в то время как CSS всегда был проблемой в React. От старых любимых css-модулей до различных производных JSS, до новых любимых styled-компонентов. Десятки решений, сотни руководств и сравнений — все это есть. Каждый всегда ищет лучшее решение для себя. Я постараюсь рассмотреть различные CSS-решения React, которые я использовал и не использовал, и, наконец, расскажу о своем любимом. Конечно, до тех пор, пока вы хотите, вполне возможно использовать обычный css или sass для завершения стиля React. Программирование так, как вам нравится больше всего, — это самое главное.
Неадекватность обычного css
Со всеми размышлениями об использовании CSS в новом режиме разработки (компонентизация) есть три основных личных резюме:
- Появляется все больше и больше ситуаций, когда стили связаны с состоянием, что требует динамического CSS, который может напрямую обращаться к состоянию компонента.
- Современная веб-разработка уже состоит из компонентов, а CSS — это не язык, рожденный для компонентизации.
- Все стили являются глобальными, что приводит к различным проблемам с именами.Правила именования, такие как БЭМ, могут решить некоторые проблемы, но при использовании сторонних подключаемых модулей невозможно избежать конфликтов именования.
Решение Vue
<style>
/* 全局样式 */
</style>
<style scoped>
/* 本地样式 */
</style>
После добавленияscoped
атрибут, css действует только на компонент, в котором он находится. Простое и красивое решение. Ложка дегтя в том, что стиль не может получить прямой доступ к состоянию компонента, поэтому необходимо указать синтаксис динамического css, который будет использоваться в сочетании с этим.
Просмотрите решение React
1. Родной
const textStyles = {
color: 'white',
backgroundColor: this.state.bgColor
};
<p style={textStyles}>inline style</p>
Нативным решением является встроенный стиль, который не пользуется уважением в старом стиле разработки, но очень подходит для разработки на основе компонентов. Встроенный стиль решает три проблемы, упомянутые ранее. А вот что лично мне не нравится, так это:
- Придуман новый набор синтаксиса css-in-js, с использованием верблюжьих имен и других правил, которые не нужно заново осваивать, чтобы не говорить, и без автоматического завершения (для удобства обсуждения этого типа написания jss ниже)
- и не поддерживает все css, такие как медиа-запросы,
:before
и:nth-child
и т.д. псевдоселекторы - Если встроенный метод записи напрямую влияет на чтение кода, если он извлечен, а затем помещен в пространство имен, он будет более громоздким, чем традиционный CSS.
- Если сторонний плагин принимает только className, но не стиль, он не будет работать.
Поскольку 1 и 3 — это просто вопрос личных предпочтений, последующая партия библиотек css-in-js настаивала на inline и jss, и посвятила себя только решению проблемы неполной поддержки css. Это популярные решения, хотя и не моя чашка чая:
2. Css-in-Js
JSS
Это улучшенная версия, специально разработанная для неадекватности нативных методов, которые не полностью поддерживают CSS.
// 支持 hover, sass的 &, media query 等。
const styles = {
button: {
fontSize: 12,
'&:hover': {
background: 'blue'
}
},
ctaButton: {
extend: 'button',
'&:hover': {
background: color('blue')
.darken(0.3)
.hex()
}
},
'@media (min-width: 1024px)': {
button: {
width: 200
}
}
}
JSS — это низкоуровневая библиотека, которую можно использовать в React, вы можете использовать React-JSS, Styled-JSS и т. д. Разнообразие вариантов является хорошим вариантом в этом типе решения.
Radium
import Radium from 'radium';
const Button = () => (
<button
style={styles.base}>
{this.props.children}
</button>;
)
var styles = {
red: {
backgroundColor: 'red'
}
};
Button = Radium(Button);
Несколько стилей легко комбинируются с помощью массивов
<button
style={[styles.base,styles.primary]}>
{this.props.children}
</button>
Используя метод HOC для внедрения стилей, удобно передавать в различных конфигурациях
Radium(config)(App)
Aphrodite
import React, { Component } from 'react';
import { StyleSheet, css } from 'aphrodite';
const Button = () => (
<span className={css(styles.red)}>
This is red.
</span>
)
const styles = StyleSheet.create({
red: {
backgroundColor: 'red'
},
});
Не все принимают написание jss. Таким образом, другое решение состоит в том, чтобы продолжать использовать css и решить проблему области действия стилей, чтобы стили влияли только на компоненты, которые их импортируют. Такие решения в настоящее время являются единственными
3. Css Modules
Модули Css не являются специфичным для React решением и применимы ко всем средам разработки, в которых используются сборщики, такие как webpack. Возьмем для примера webpack, открываем его в опциях css-loadermodules:true
возможность использовать модули Css.
Общая конфигурация выглядит следующим образом
{
loader: "css-loader",
options: {
importLoaders: 1,
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]" // 为了生成类名不是纯随机
},
},
Используйте следующим образом
import styles from './table.css';
render () {
return <div className={styles.table}>
<div className={styles.row}>
<div className={styles.cell}>A0</div>
<div className={styles.cell}>B0</div>
</div>
</div>;
}
/* table.css */
.table {}
.row {}
.cell {}
Небольшое сожаление при обращении к прицелу:
- Имя класса должно быть в верблюжьем регистре, иначе его нельзя будет нормально использовать в js.
styles.table
Цитировать - Поскольку модульность css используется по умолчанию, когда вы хотите использовать обычный глобальный css, вам нужно передать
:local
и:global
переключение, неудобно - Все className должны использовать
{style.className}
форма
Это большое преимущество, что этот обходной путь может писать css как обычно, но я не выношу сравнения 2,3. легкийbabel-plugin-react-css-modulesБиблиотека предлагает решение. Вы можете писать «размер таблицы» и другие имена классов с горизонтальными полосами, как обычно, и писать строковые имена классов, как обычно, в js. Единственное отличие состоит в том, чтобы использоватьstyleName
замена ключевых словclassName
, приведенный выше пример, результат выглядит следующим образом
import './table.css';
render () {
return <div styleName='table'>
<div styleName='row'>
<div styleName='cell'>A0</div>
<div styleName='cell'>B0</div>
</div>
</div>;
}
Используя новое ключевое слово styleName, даже различие между локальным css и глобальным css легко решается.
<div className='global-css' styleName='local-module'></div>
при его использовании.babelrc
Конфигурация:
{
"plugins": [
["react-css-modules", {
// options
}]
]
}
Это решение довольно близко к моему вкусу, но с использованиемstyleName
Что мне делать, если я столкнусь со сторонней библиотекой пользовательского интерфейса?
Кстати, в настоящее времяcreate-react-app
Модули Css пока не поддерживаются, но находятся в стадии бета-тестирования.create-react-app v2
уже поддерживается. Метод использования заключается в том, чтобы всегда называть файл css какXXX.modules.css
, приведенный выше примерtable.modules.css
, может быть использован. Элегантность этого решения заключается в том, что глобальный css можно использовать как обычно, только с.modules.css
Суффикс будет иметь размер модуля.
Css Modules по-прежнему имеет большой недостаток: как и решение Vue, поскольку css написан в файлах css, он не может обрабатывать динамический css.
4. Новая волна Css-in-Js
Есть много людей, которые не покупают учетные записи JSS (я считаю одного), и решение Vue также является источником вдохновения, поэтому новая библиотека пытается использовать строки шаблонов ES6 и писать чистый CSS в файлах js.
`
.table {
background: #333;
color: rebeccapurple;
}
`
Это очень естественно решает 2 упомянутых недостатка нативного метода: не весь синтаксис CSS поддерживается. Самыми известными из этих решений являются стилизованные компоненты, а аналогичные — Emotion. Поначалу основным неудобством этого метода было то, что редактор не мог форматировать, линтинговать и автоматически дополнять CSS в js, но сейчас практически в каждом популярном редакторе можно найти соответствующий плагин для решения этой проблемы.
styled-components
import styled from 'styled-components';
// `` 和 () 一样可以作为js里作为函数接受参数的标志,这个做法类似于HOC,包裹一层css到h1上生成新组件Title
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// 在充分使用css全部功能的同时,非常方便的实现动态css, 甚至可以直接调用props!
const Wrapper = styled.section`
padding: 4em;
background: ${props => props.bgColor};
`;
const App = () => (
<Wrapper bgColor='papayawhi'>
<Title>Hello World, this is my first styled component!</Title>
</Wrapper>
)
Стоит отметить, что ссылки на другие элементы поддерживаются, а синтаксис довольно естественен:
const Link = styled.a`
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
`;
const Icon = styled.svg`
transition: fill 0.25s;
width: 48px;
height: 48px;
${Link}:hover & {
fill: rebeccapurple;
}
`;
и может быть легко раскрытclassName
Стиль в сторонней UI-библиотеке реквизита:
const StyledButton = styled(Button)` ... `
Некоторым людям нравится переименовывать каждый тег, для которого требуется стиль, в более осмысленное имя, но другим такое переименование кажется утомительным. Такие люди могут попробовать Emotion
Emotion
import styled, { css } from 'react-emotion'
const Container = styled('div')`
background: #333;
`
const myStyle = css`
color: rebeccapurple;
`
const app = () => (
<Container>
<p className={myStyle}>Hello World</p>
</Container>
)
Emotion поддерживает метод внедрения стилей для styled-components, а также может использоватьcss()
Ключевые слова вводятся напрямую. Также поддерживает JSS и& :hover
и т.д. Синтаксис Sass, например:
// sass
<div
className={css`
background-color: hotpink;
&:hover {
color: ${color};
}
`}
>
// JSS
<div
className={css({
backgroundColor: 'hotpink',
'&:hover': {
color: 'lightgreen'
}
})}
>
Раньше я этого не замечал, Emotion позволяет напрямую писать стили дочерних элементов!
import { css } from 'emotion'
const paragraph = css`
color: turquoise;
a {
border-bottom: 1px solid currentColor;
}
`
render(
<p className={paragraph}>
Some text. <a>
A link with a bottom border.
</a>
</p>
)
При использованииbabel-plugin-emotion
, вы даже можете использовать CSS напрямую в качестве реквизита:
<div
css={`
color: blue;
font-size: ${props.fontSize}px;
&:hover {
color: green;
}
& .some-class {
font-size: 20px;
}
`}
>
Очень просто и уникально, и предлагает решения на любой вкус.
Glamorous
Glamorous имеет много общего с первыми двумя библиотеками, самая большая разница в том, что она привязана к передней части JSS. Строки шаблона не поддерживаются для написания чистого CSS. Существует три варианта базового использования Glamorous:
import
import glamor from 'glamorous'
// className 注入
const styles = glamor.css({
fontSize: 20,
textAlign: 'center',
})
<div
className={styles}
/>
// 2. 类styled components
const MyStyledDiv = glamor.div({margin: 1, fontSize: 1, padding: 1})
// 3. 使用自带组件,接受样式名和css为props
const { Div } = glamor
<Div
fontSize={20}
textAlign="center"
css={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center'
}}
>
Hello world!
</Div>
// 4. 以及混用
const MyStyledDiv = glamor.div({margin: 1, fontSize: 1, padding: 1})
const myCustomGlamorStyles = glamor.css({fontSize: 2})
<MyStyledDiv className={`${myCustomGlamorStyles} custom-class`} />
Последний разговор, мой любимый
1. styled-jsx
Продукт Next.js zeit должен быть бутиком.
2. Неожиданные решения (личная любовь)
Две библиотеки css, идущие совершенно другим путем, чем бутстрап, так называемые «атомарные классы». По сути, первое, что я делаю при написании небольших проектов и демонстраций, это
yarn add tachyons
Длина неожиданно слишком длинная, в следующей части я объясню эти два личных предпочтительных решения. В этой статье сделан небольшой обзор текущих популярных решений. Всем удобно спрашивать и выбирать. В этой статье я использую наиболееstyled-components
, но теперь перешел наstyled-jsx
. Следующее, что я хочу попробовать, должно бытьEmotion
. В конце концов, нет лучше или хуже, это скорее личные предпочтения. Надеюсь, что это резюме будет полезным для вас. Недостатки, пожалуйста, оставьте сообщение, чтобы указать, учиться друг у друга, спасибо!
Середина:Расскажите о моих фаворитах из 10 популярных решений CSS (посередине)