Стилизация компонентов приложения React с помощью Fela
Development, Java | Комментировать запись
Стили в React бывают всех видов, форм и размеров. По умолчанию вы можете присваивать классы через свойство className. Также можно присваивать свойства CSS, передавая объект свойству style. В большинстве сценариев этих методов более чем достаточно, однако они, конечно, не лишены недостатков. К примеру, чтобы сделать classNames динамическим, необходимо определить дополнительные классы и свойства style; а чтобы разрешить использование динамических свойств, требуется шаблонный код, который не дает углубиться в свойства псевдоклассов типа :hover. Как раз для таких ситуаций и придумали Fela.
Fela – это не зависящая от фреймворка библиотека JavaScript для обработки стилей на основе состояния. Она очень мощная и довольно гибкая. Fela можно использовать отдельно, а можно вместе с react-fela – библиотекой привязок React для ваших приложений React.js.
Начало работы с Fela
Для начала нужно добавить react-fela в свой проект. Это можно сделать через npm:
$ npm install --save react-fela
Или через Yarn:
$ yarn add react-fela
В этом руководстве мы будем использовать некоторые методы прямо из библиотеки fela. Но не волнуйтесь, react-fela включает эту зависимость, так что все будет в порядке, если вы захотите добавить ее.
Что такое createRenderer
Часть библиотеки fela, которую мы будем использовать здесь, называется createRenderer. Метод createRenderer используется для создания средства визуализации, которому будет передан компонент Provider – он, в свою очередь, создаст оболочку для всех компонентов, использующих Fela.
Все дальнейшие наши примеры будут содержать шаблонный код, который нужен для того, чтобы чудо все-таки произошло.
Использование сгенерированных CSS-классов
Ниже вы найдете не самый сложный пример Fela: он не идеален, но в нем меньше всего шаблонного кода.
Основной принцип работы Fela заключается в том, что он принимает предоставленные стили, генерирует соответствующий CSS с атомарными классами и позволяет извлечь полученные CSS-классы, которые можно передать в свойство classNames любого компонента:
import React from "react";
import { render } from "react-dom";
import { createRenderer } from "fela";
import { Provider } from "react-fela";
const renderer = createRenderer();
const rule = ({
backgroundColor = "#6db65b",
borderColor = "#efbb35",
padding
}) => ({
backgroundColor: backgroundColor,
border: `10px solid ${borderColor}`,
color: "#fff",
fontWeight: "bold",
padding: `${padding}px`,
":hover": {
cursor: "pointer",
filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
}
});
const container = document.createElement("div");
document.body.appendChild(container);
render(
<Provider renderer={renderer}>
<div className={renderer.renderRule(rule, { padding: 100 })}>
Hover Over Me!
</div>
</Provider>,
container
);
Как вы можете видеть в этом примере, renderer используется для генерации CSS и имен классов на основе объекта передаваемых CSS-свойств.
rule – это простая анонимная функция, которая возвращает объект со всеми переданными свойствами.
Поскольку rule – это просто функция с возвращаемым объектом, вместо немедленного возврата ожидаемого объекта вы можете по своему усмотрению включить дополнительную логику.
Использование компонентных примитивов
Подход, который мы рассмотрели в предыдущем примере, работает достаточно хорошо, но иногда лучше создать новый компонент, который можно повторно использовать в проекте.
В подобных сценариях мы могли бы использовать примитив FelaComponent для создания нового компонента:
import React from "react";
import { render } from "react-dom";
import { createRenderer } from "fela";
import { FelaComponent, Provider } from "react-fela";
const renderer = createRenderer();
const rule = ({
backgroundColor = "#6db65b",
borderColor = "#efbb35",
padding
}) => ({
backgroundColor: backgroundColor,
border: `10px solid ${borderColor}`,
color: "#fff",
fontWeight: "bold",
padding: `${padding}px`,
":hover": {
cursor: "pointer",
filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
}
});
const PaddedContainer = ({
backgroundColor,
borderColor,
padding,
children
}) => (
<FelaComponent
rule={rule}
backgroundColor={backgroundColor}
borderColor={borderColor}
padding={padding}
>
{children}
</FelaComponent>
);
const container = document.createElement("div");
document.body.appendChild(container);
render(
<Provider renderer={renderer}>
<PaddedContainer padding={100}>
Hover Over Me!
</PaddedContainer>
</Provider>,
container
);
Используя аналогичную функцию rule, мы можем создать новый компонент PaddedContainer, которому можно передавать свойства напрямую, без лишних ресурсных расходов и присвоения классов через renderRule.
Самостоятельное создание компонентов
Нет ничего плохого в использовании примитивов для создания новых компонентов, но, как правило, при этом получается немного больше шаблонного кода:
import React from "react";
import { render } from "react-dom";
import { createRenderer } from "fela";
import { createComponent, Provider } from "react-fela";
const renderer = createRenderer();
const rule = ({
backgroundColor,
borderColor,
padding
}) => ({
backgroundColor: backgroundColor,
border: `10px solid ${borderColor}`,
color: "#fff",
fontWeight: "bold",
padding: `${padding}px`,
":hover": {
cursor: "pointer",
filter: "drop-shadow(0 10px 19px rgba(0, 0, 0, 0.3))"
}
});
const AnotherPaddedContainer = createComponent(rule);
const container = document.createElement("div");
document.body.appendChild(container);
render(
<Provider renderer={renderer}>
<AnotherPaddedContainer padding={100}>Hover Over Me!</AnotherPaddedContainer>
</Provider>,
container
);
Получается немного чище. Такой код можно использовать повторно (точно так же, как пример с компонентными примитивами).
Заключение
Независимо от того, какой подход вы выберете, вы по-прежнему можете сократить время, необходимое для динамической стилизации компонентов в React – для этого обратитесь к react-fela. Эта библиотека сокращает количество шаблонов, которые нужно написать.
Увидеть приведенные выше примеры кода в действии можно в этой песочнице CodeSandbox.
Читайте также: Промисы в JavaScript ES6/ES2015
Tags: CSS, Fela, Javascript, React