Расширение CSS-in-JS для поддержки синтаксиса стилевых компонентов

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

const Button = styled('button')(
  {
    backgroundColor:  "blue",
    color: "white"
  }
)
Вход в полноэкранный режим Выход из полноэкранного режима

При изучении API следует обратить внимание на несколько моментов:

// On breaking into parts: 
const Button = // <-- Part: 3
styled('button') // <-- Part: 1
({ backgroundColor: 'blue' }) // <-- Part: 2

Вход в полноэкранный режим Выход из полноэкранного режима
  • Часть 1: Функция styled принимает tagName, которое должно быть создано, т.е.
 styled('button') <-- 1

// is equivalent to

<button>
Войти в полноэкранный режим Выход из полноэкранного режима
  • Часть 2: Функция styled(tagName) возвращает функцию, которая принимает style-object, который будет использоваться для стилизации этого элемента tagName.
({ backgroundColor: "blue" }) <-- Part 2

// is converted to 

css({ backgroundColor: "blue" }) 

// and passed to the component as

<button className={css(...)} />
Вход в полноэкранный режим Выйти из полноэкранного режима
  • Полный вызов возвращает компонент React Button, который отображает button с заданным стилем.

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

// Part 1: styled('button'): element of type tagName to render
function styled(tagName) { 
  // Part 2: style('button')({ color: 'white' }) takes in the style object and applies these styles to `tagName=button` component

  return function applyStyles(styleObject) { 
      // Part 3: `Button` react component 
      return function Component(props) { 
          // ...styling and element creation... 
          // Mark: 1
      }
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь на месте Mark: 1 нам нужно сделать следующее:

  • Создать элемент с помощью React.createElement типа tagName.
  • Передайте style-object в функцию css для генерации имени, так как реквизиты могут уже содержать некоторые className, поэтому составьте эти className вместе.
// continue from Mark: 1

const clonedProps = clone(props);
// a copy of props is required as by default react makes props immutable
// and if we want to modify any props we need to make a copy for our use

// compute a className for styleObject
const generatedClassName = css(styleObject);

// compose className 
const className = generatedClassName + props.className ? + ` ${props.className}` : '';

// reassign composed className
clonedProps.className = className;

// create element of type `tagName` with props = `clonedProps` and `style=generateClassName`
const element = React.createElement(tagName, clonedProps);

// The `element` is of type `tagName` and of `styles=styleObject` this is one we want to render

return element;
Вход в полноэкранный режим Выйти из полноэкранного режима

Вот как выглядит style-components версия нашей библиотеки CSS-in-JS. Функция clone может быть такой же простой, как:

const clone = (obj) => Object.assign({}, obj);
Войти в полноэкранный режим Выйти из полноэкранного режима

Больше информации о CSS-in-JS:

  • Почему CSS-in-JS?
  • CSS: Изоляция против абстракции
  • Создайте свою собственную библиотеку эмоций, подобную CSS-in-JS
  • Styler GitHub
  • Styler Codesandbox

Оцените статью
devanswers.ru
Добавить комментарий