Я ехал на поезде CSS-in-JS в течение многих лет (я был даже значительным
участник "движения"). Это круто. Я никогда не был таким продуктивным
работы с CSS, чем когда я добавил к нему настоящий язык программирования.
Я все еще поклонник CSS-in-JS, и в последние годы спецификация CSS претерпела изменения и
значительно улучшились, и современные браузеры тоже (к сожалению, Internet Explorer
НЕ современный браузер в этом или другом контексте). Часто я использовал ThemeProvider
(например, эмоции), но оказывается, что
преимущества такого компонента во многих случаях использования, и есть несколько
Недостатки.
Давайте посмотрим на простой пример «Темного режима» и сравним различия в API
(опыт разработчика) и производительность (пользовательский опыт). Сохраним пример
просто, и как до, так и после, мы будем использовать утилиту эмоционального стиля
.
Помните, что с ThemeProvider
вы можете использовать значения, используя
крючок useTheme
со стилизованным компонентом или с css
prop. С CSS
Переменные, вы можете получить значения в вашем CSS с помощью var (- css-variable-name)
и в вашем JavaScript, используя
getComputedStyle (element) .getPropertyValue ('- css-variable-name')
(который вы
действительно не нужно делать …)
Хорошо, давайте посмотрим на код. Вот подход к использованию эмоций
ThemeProvider
:
импорт * as Реагировать из 'реагировать'
импорт стилизован из '@ эмоциональный / стилизованный'
импорт { ThemeProvider } из ] «тема эмоций»
const темы = {
свет : {
цвета : {
первичный : 'deeppink'
фон : «белый»
] }
}
темный : {
цвета : {
первичный : 'lightpink'
фон : 'черный'
}
}
}
const PrimaryText = в стиле . div ( ( { тема } ) => ( {
набивка ]: [1 9459010] 20
цвет : тема . цвета . первичный
backgroundColor : тема . цвета . фон
} ) )
функция ThemeToggler ( { тема onClick } ) {
] const nextTheme = theme === 'свет' ? «темный» : «свет»
возврат (
< кнопка при нажатии = { ( ) => onClick ( nextTheme ) } >
Измените на { nextTheme } режим
кнопка < / кнопка >
)
}
функция Приложение ( ) {
const [ тема setTheme ] = React . useState ( 'светлый' )
return (
< ThemeProvider тема = { темы [ тема ] } >
< PrimaryText > Этот текст является основным цветом < / PrimaryText >
< ThemeToggler
тема = { тема }
onClick = { ( nextTheme ) => setTheme ( nextTheme ) }
/ >
< / ThemeProvider >
)
]}
экспорт по умолчанию Приложение
Что в этом круто, так это то, что это "просто JavaScript", поэтому вы получаете все преимущества
переменные и т. д. Но на самом деле мы мало что делаем с этим, кроме
передавая его через ThemeProvider. (Чтобы было ясно, как
ThemeProvider работает, если использует контекстный API React, чтобы сделать тему доступной.
ко всем компонентам эмоций без необходимости передавать реквизиты повсюду).
Давайте сравним это с подходом CSS Variables. Но прежде чем мы дойдем до этого, я
Следует отметить, что для этого не существует "ThemeProvider". Вместо этого мы определяем
переменные в обычном CSS, которые будут применяться на основе атрибута data
который мы
применяется к корпусу
. Итак, вот этот файл css:
body [ data-theme = 'свет ' ] {
- основные цвета : deeppink ;
- цвета-фон : белый ;
}
тело [ тема данных = «темный» ] {
- основные цвета : светло-розовый ;
- цвета-фон : черный ;
}
Хорошо, вот и реализация того же пользовательского интерфейса:
импорт * как React из 'реагировать'
импорт './ css-vars.css'
импорт в стиле из ] '@ эмоции / стили'
const P rimaryText = в стиле . div ( {
набивка : 20
]цвет : 'var (- основные цвета)'
backgroundColor : 'var (- цвета-фон)'
} )
функция ThemeToggler ( ) {
const [ тема setTheme ] = React . useState ( 'свет' )
const nextTheme = тема === 'светлый' ? ' темный ' : ' светлый '
React . useEffect ( ( ) = > {
документ . тело ] . набор данных . тема = тема
} [ тема ] )
возврат (
< кнопка при нажатии = { ( ) => setTheme ( nextTheme ) } >
Измените на { nextTheme } режим
< / кнопка >
)
}
функция Приложение ( ) {
возврат ( ]
< div >
< PrimaryText > Этот текст является основным цветом < ] / PrimaryText >
< ThemeToggler / >
< / div >
)
}
экспорт по умолчанию Приложение
Давайте сначала сравним, каково использовать эти значения:
const PrimaryText = в стиле . div ( ( { тема } ) => ( {
набивка : 20
цвет : тема . цвета . первичный
backgroundColor : тема . цвета . фон
} ) )
const PrimaryText = в стиле . ] div ( {
отступы : 20
цвет : 'var (- цвета -primary) '
backgroundColor : ' var (- -colors-background) '
} )
Нет союзник сильно отличается от DX (опыт разработки)
точка зрения здесь. Один из аргументов в пользу подхода с использованием переменных CSS — отсутствие необходимости
создать функцию, которая принимает тему и возвращает стили (и нет необходимости
даже узнать об этом API).
Один из достоинств подхода ThemeProvider
: если вы используете TypeScript, вы
может обеспечить безопасность типов в вашей теме … Но ммм …
Проверьте это:
const тема = {
цвета : {
первичный : 'var (- основные цвета)'
фон : 'var (- цвета-фон)'
}
}
экспорт { тема }
импорт { тема } из ] 'тема'
const PrimaryText = в стиле . div ( {
набивка : 20
цвет : тема . цвета . первичный
backgroundColor : тема . цвета . фон
} )
БУМ. Дружественный к статической типизации.
В любом случае, это единственное существенное отличие DX. Рассмотрим
Разница в UX (пользовательском опыте). Почему бы вам не поиграть с ним:
Вы заметите, что на самом деле нет никакой наблюдаемой разницы в UX, и нет
для этого простого примера. Но почему бы вам не попробовать это со мной:
- откройте React DevTools Profiler
- Начните сеанс профилирования (щелкните маленький кружок)
- Щелкните значок кнопка переключения для каждого
- Остановить сеанс профилирования
- Сравните две фиксации
Вот что я вижу:
ThemeProvider: