Введение
В последнее время я играю со styled-components. Это библиотека CSS-in-JS, которая использует тегированные литералы шаблонов. Я хочу рассказать о трех концепциях, которые меня озадачили: Interpolation
, GlobalStyle
и ThemeProvider
.
Что такое интерполяция?
Интерполяция — это адаптация компонента на основе переданных ему реквизитов; это означает, что вы можете вводить значения через реквизиты. Например:
const MockElement = styled.div`
--size: ${(props) => (props.big ? '100px' : '50px')};
width: var(--size);
height: var(--size);
background-color: yellowgreen;
`;
render(
<div>
// This renders a 50x50 square, because there was no "big" prop
<MockElement />
// This renders a 100x100 square, because "big" was passed
<MockElement big />
<div>
)
Таким образом, вы можете использовать реквизиты как истинные значения. А как насчет пользовательских значений? Это тоже работает!
const MockElement = styled.div`
background-color: ${props => props.color ? props.color : 'yellowgreen'};
--size: ${(props) => (props.big ? '100px' : '50px')};
width: var(--size);
height: var(--size);
`;
render(
<div>
// This renders a blue square
<MockElement color='blue'/>
// This renders... no color??
<MockElement color />
<div>
)
Стилизованные реквизиты по умолчанию являются истинными, но поскольку значение не было передано, ничего не будет отображено. Чтобы использовать значение по умолчанию с помощью этой техники, вы либо полностью пропускаете реквизит, либо передаете null
.
Но будьте осторожны! Вы должны передать функцию при интерполяции значения, иначе код сломается. Что-то вроде следующего не будет работать:
const MockElement = styled.div`
background-color: ${props.color}; /* It must be a function */
`;
Должна ли функция быть встроенной? Нет! Вы можете просто передать любую функцию в качестве обратного вызова:
function declaredFunction (props) {
let scale = `${props.factor * 50}px`
return scale
}
const MockElement = styled.div`
--size: ${declaredFunction};
width: var(--size);
height: var(--size);
background-color: ${props => props.color ? props.color : 'yellowgreen'};
`;
render(
<div>
// This renders a 150x150, yellowgreen square
<MockElement big color={null} factor={3}/>
<div>
)
На этом изучение интерполяции
заканчивается. Переходим к следующему!
Что такое GlobalStyle?
Компонент GlobalStyle, как понятно из названия, используется для определения общих правил стилизации приложения. Близким сравнением будет использование файла index.css
, который импортируется и собирается перед всеми другими таблицами стилей, таким образом, перезаписываясь последующими модулями css.
Использование глобального стиля довольно просто! Сначала необходимо создать файл GlobalStyle.js
, как показано ниже:
import { createGlobalStyle } from 'style-components';
const GlobalStyle = createGlobalStyle`
/* Insert global styling here */
`;
export default GlobalStyle;
Затем поместите компонент… куда угодно, на самом деле. По крайней мере, в тех нескольких тестах, которые я проводил, я размещал компонент в любом месте проекта, и он прекрасно работал. Однако для организации я разместил свою систему маршрутизации (с помощью react-router) следующим образом:
# App.js
import GlobalStyle from './utils/GlobalStyle';
function App() {
return (
<BrowserRouter>
<GlobalStyle />
<Routes>
{/*The routes and elements go here*/}
</Routes>
</BrowserRouter>
);
}
Круто! Переходим к последней теме: ThemeProvider
.
Что такое ThemeProvider?
ThemeProvider — это источник универсальных реквизитов для всех своих дочерних компонентов. Вы должны поместить компонент в корень вашего проекта, если хотите, чтобы все компоненты имели к нему доступ.
Так, если вы используете App.js
в качестве корня, вы можете сделать что-то вроде:
#App.js
import { ThemeProvider } from 'styled-components';
const themeObject = {
button : {
primary : {
background: 'lightblue',
color: 'white',
},
secondary: {
/* other keywords*/
}
}
}
function App() {
return (
<ThemeProvider theme={themeObject}>
<CoolButton />
</ThemeProvider>
);
}
Этот themeObject
становится доступным для всех объектов, которые являются дочерними для ThemeProvider
. Вы используете реквизит theme
через interpolation
, вот так:
#CoolButton.styled.js
import styled from 'styled-components';
const CoolButton = styled.button`
background-color: ${props => props.theme.button.primary.background};
/* As seen above and below, you just need to access the string from the theme object */
color: ${props => props.theme.button.primary.color};
`
Вы также можете объединить все три компонента, сделав GlobalComponent
дочерним ThemeProvider
и интерполируя значения по мере необходимости. Один из полезных примеров — установка семейства шрифта.
# theme.js
const theme = {
heading: "Cool Heading",
subHeading: "Cute Heading"
};
export default theme;
# GlobalStyle.js
import { createGlobalStyle } from 'styled-components';
import coolFontPath from './font-file1.woff';
import cuteFontPath from './font-file2.woff';
const GlobalStyle = createGlobalStyle`
@font-face {
font-family: 'Cool Heading';
src: url(${coolFontPath};
}
@font-face {
font-family: 'Cute Heading';
src: url(${cuteFontPath};
}
h1 {
font-family: ${props => props.theme.heading};
}
span.subheading {
font-family: ${props => props.theme.subHeading}
}
`
export default GlobalStyle;
# App.js
import GlobalStyle from './GlobalStyle.js';
import theme from './theme.js';
import { ThemeProvider } from 'styled-components';
const App = () => {
return (
<ThemeProvider theme={theme}>
<h1>I belong to the Cool Heading family</h1>
<span className='subheading'>
I belong to the Cute Heading family
</span>
</ThemeProvider>
);
}
Резюме
Ну вот и все! Это было изучение трех важных концепций библиотеки стилей: Interpolation
, GlobalStyling
и ThemeProvider
. Надеюсь, это было полезно!