CSS Modules

внешний интерфейс Vue.js React.js CSS

            CSS Modules

Стандарт именования CSS — это, по сути, проблема, с которой приходится сталкиваться каждой команде.Стандарт будет, но в конечном итоге всегда сложно строго его реализовать.

Когда я впервые пришел в команду компании, все следовали правилу «имя по фамилии» и продвигали его.

Например, следующая общая структура модуля информации о продукте:

<div class="gb_goods_item">
	<div class="gb_goods_item_box">
	  <div class="gb_goods_item_image">
	    ...
	  </div>
	  <div class="gb_goods_item_info">
	    <div class="gb_goods_item_title">
	      ...
	    </div>
	    <div class="gb_goods_item_sidebar">
	      <div class="gb_goods_item_price">
	        ...
	      </div>
	      <div class="gb_goods_item_shopcart">
	        <div class="gb_shopcart">
	          ...
	        </div>
	      </div>
	    </div>
	  </div>
	</div>
</div>

Этот набор правил фокусируется на выражении и управлении семантикой CSS.Первоначальная цель состоит в том, чтобы облегчить идентификацию владельца стилевых модулей и облегчить повторное использование в будущем, что немного похоже на метод БЭМ. Но очевидны и недостатки: сложно понять, и долго учитывать его уникальность.При достаточно сложном коде структуры «потомка» именование будет слишком длинным и недостаточно гибким, и еще есть нет способа вылечить загрязнение кода и проблемы с загрязнением.

Когда я только начал им пользоваться, я к нему не привык, и было много споров, каждый раз, когда приходил новый сотрудник, требовалось много времени на объяснение, и было сложно заставить его на 100% хотеть его использовать. Даже если есть четкий документ спецификации команды, он действительно есть в сети, иногда все равно будет «нестандартный» код.

Тем не менее, взвесив все за и против, я настоял на его использовании. Когда Node появился и окреп, мир фронтенда развивался чрезвычайно быстро, а рабочий процесс фронтенда становился более детализированным. Рождение React, компонентизация, подчеркивающая преимущества сверхбольшой и эффективной совместной работы, стала еще более популярной, а независимость и широкие возможности повторного использования компонентизации призваны снять ограничения CSS на компоненты: проблему загрязнения кода стиля.

"Имя по фамилии" явно не может соответствовать этому требованию. Ведь стили CSS всегда используются глобально. Каким бы уникальным ни было "Имя", всегда будут возможности для одного и того же имени и фамилии. На этом этапе CSS-модули представляют собой хорошее решение.

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default.

Область действия всех имен классов и анимаций в файлах CSS по умолчанию соответствует текущей области.

CSS-модули дают представление о предметной области CSS, давайте сначала рассмотрим волну CSS-модулей в практическом применении.

Распространенные карусели в компонентах React:

Визуализировать содержимое JSX:

import styles from './styles/FocusSlider.css';

// FocusSlider
render() {
  return (
	  <div className={styles.fsSlider} data-role="fsSlider">
	    <div className={styles.fsSliderMain}>
	      <Slider
	        sliderData={this.state.sliderData}
	      />
	    </div>
	    <div className={styles.fsSliderBg}></div>
	    {/* 数据重加载提示 */}
	    <DataReqReload
	      isShow={this.state.isReloadData}
	      doReload={this.doReload}
	    />
	  </div>
  );
}

соответствующийFocusSlider.scss:

:local{
  .fsSlider{
    position: relative;
    padding-top: -webkit-calc(100vw * 120 / 1125);
    padding-top: calc(100vw * 120 / 1125);
  }

  .fsSliderMain{
    position: relative;
    z-index: 1;
    min-height: -webkit-calc( ((100vw - 60px) * 570 / 960) + ((100vw - 60px) * 70 / 1125) );
    min-height: calc( ((100vw - 60px) * 570 / 960) + ((100vw - 60px) * 70 / 1125) );
  }
  
  .fsSliderBg{
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: -webkit-calc(100vw * 588 / 1125);
    height: calc(100vw * 588 / 1125);
    background: #000 url(../../../images/top100/fs_bg.jpg) no-repeat;
    background-size: 100% auto;
  }

  .gbSlider{
    background: #000;
  }
}

Скомпилированный код выглядит так:

<div class="_1zbnOjlYzV-MBq1JhiGcZF" data-role="fsSlider">
    <div class="svXZ19tF2m_fbg8KuFb6T">
        <div class="lvyQyG394l5agFQKH8_du" data-role="gbSlider" style="opacity: 1;">
            ...
        </div>
    </div>
    <div class="_27Jm0ogj1EtOf2dNHKvKC1"></div>
    <!-- 数据重加载提示 -->
    <div class="f1qHBJK89yiiDn4Tcb2It _3grBcj2DcL0IJGuHXl4LK6" data-role="reloadBox">
        ...
    </div>
</div>

можно увидеть,FocusSlider.scssИмя в стиле локального домена, определенное в нем, стало хэш-строкой, и в то же времяFocusSlider.cssфайл также будет скомпилирован

._1zbnOjlYzV-MBq1JhiGcZF {
    position:relative;
    padding-top:calc(100vw * 120 / 1125)
}
.svXZ19tF2m_fbg8KuFb6T {
    position:relative;
    z-index:1;
    min-height:calc(((100vw - 60px) * 570 / 960) + ((100vw - 60px) * 70 / 1125))
}
._27Jm0ogj1EtOf2dNHKvKC1 {
    position:absolute;
    left:0;
    right:0;
    top:0;
    height:calc(100vw * 588 / 1125);
    background:#000 url(/static/media/fs_bg.70affa5b.jpg) no-repeat;
    background-size:100% auto
}
._2EHIbU8ioFFyvcDBD64P4_ {
    background:#000
}

Css-модули делают имя класса стиля уникальным в локальной области видимости, не загрязняя глобальный стиль, а это именно то, в чем отчаянно нуждается компонентизация и, похоже, она родилась для React.

Таким образом, приведенная выше информационная структура продукта «имя на основе фамилии» может быть записана в модулях Css следующим образом:

import styles from '../styles/GoodsItem.css';

render() {
  return (
    <div class={styles.goodsItem}>
      <div class={styles.itemBox}>
        <div class={styles.image}>
          ...
        </div>
        <div class={styles.info}>
          <div class={styles.title}>
            ...
          </div>
          <div class={styles.sideBar}>
            <div class={styles.price}>
              ...
            </div>
            <div class={styles.shopCart}>
              <ShopCart
                sku={}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Это позволяет нам больше сосредоточиться на разработке компонентов. Итак, как его использовать? На самом деле довольно просто использовать

  • Если вы используете React и используете отличныйCreate React App, по умолчанию поддерживаются модули Css.
  • Если вы используете Vue, поздравляю, вам не нужно об этом беспокоиться, Vue имеет собственную обработку полей стилей;
  • Если нет, то вам, вероятно, нужен Webpackcss-loader, где вы также можете настроить имя хеш-класса.
  • вы также можете использоватьPostCSS-Modules,PostCSS Плагин для Css Mudous где угодно 😳

Более конкретную документацию можно найти на github.css-modules

Вы также можете посмотреть на Учителя Руана.«Учебник по использованию модулей CSS»

Хотя модули Css очень круты в использовании, в практическом применении есть ложка дегтя, то есть настройка компонентов в локальной области видимости, наиболее распространенным является требование «скининга», как показано ниже

Структура данных и источник данных двух списков продуктов на приведенном выше рисунке одинаковы, но макет и стиль немного отличаются.Если вы используете традиционную схему CSS для написания стиля, вы сначала напишете справочный стиль, а затем напишите стиль "кожа":

<div class="goods goods_a">
  <div class="goods_item">
    ...
  </div>
</div>

<div class="goods goods_b">
  <div class="goods_item">
    ...
  </div>
</div>

В компонентной системе приведенный выше список товаров может иметь следующую структуру:

Контейнеры в товарахGoodsContaninerкомпонент

import styles from '../styles/GoodsContainer.css';

render() {
  return (
    <div className={style.goodsContainer}>
      <GoodsA>
        <GoodsItem />
      </GoodsA>

      <GoodsB>
        <GoodsItem />
      </GoodsB>
    </div>
  );
}

еслиGoodsA,GoodsBа такжеGoodsItemВсе они являются независимыми компонентами, и стили, соответствующие модулям Css, также не зависят от локальной области видимости.GoodsAа такжеGoodsBне может быть правGoodsItemВыполните настройку стиля.

В этом случае вы можете написать расширенные свойства для стилей в структуре компонента, как вGoodsItemКомпонент записывается так:

import styles from '../styles/GoodsItem.css';

render() {
  return (
    <div className={style.goodsItem} data-role="goodsItem">
      ...
    </div>
  );
}

так вGoodsAа такжеGoodsBможно контролировать вGoodsItemохватывать

:local {
	.goodsA{
		[data-role="goodsItem"] {
			...
		}
	}
}

Вы спросите, а не было бы хлопотно писать так? Этого сценария можно полностью избежать путем предварительного планирования, такого как планированиеGoodsItemОбласть стиля компонента (глобальная область) или структура компонента проектируется заранее, а пара параметров зарезервирована.GoodsItemКомпоненты для управления стилем.

Однако, в процессе реальной итерации проекта, иногда мы не можем предсказать масштаб последующего развития проекта, очень вероятно, что в компонентах, которые вы написали в первой версии, будут продолжать итерироваться функции, такие как "скининг" сценарий упомянутый выше. необходимо написатьdata-roleРасширенные стили для компонентов.

Если есть проект с использованием компонентной системы, CSS Modules — лучший выбор для подбора CSS-решений.

Строка из фильма может точно описать настроение после использования CSS-модулей: «Если вы когда-нибудь были ослом, то вы перевернете голову».