Как элегантно использовать CSS-модули в Vue?

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

Vue CSS Modules

Модули CSS: локальная область действия и модульность

CSS ModulesДайте каждому локальному классу глобально уникальное имя класса, чтобы стили компонентов не влияли друг на друга. Такие как:

/* button.css */
.button {
  font-size: 16px;
}
.mini {
  font-size: 12px;
}

Он будет преобразован во что-то вроде этого:

/* button.css */
.button__button--d8fj3 {
  font-size: 16px;
}
.button__mini--f90jc {
  font-size: 12px;
}

При импорте файла модуля CSS он предоставляет нам объект сопоставления имен локальных классов с именами глобальных классов. так:

import styles from './button.css'
// styles = {
//   button: 'button__button--d8fj3',
//   mini: 'button__mini--f90jc'
// }

element.innerHTML = '<button class="' + styles.button + ' ' + styles.mini + '" />'

vue-css-modules: Упрощенное сопоставление имен классов.

Вот компонент кнопки с использованием модулей CSS:

<template>
  <button :class="{
    'global-button-class-name': true,
    [styles.button]: true,
    [styles.mini]: mini
  }">点我</button>
</template>

<script>
  import styles from './button.css'

  export default {
    props: { mini: Boolean },
    data: () => ({ styles })
  }
</script>

Действительно, CSS-модули — хороший выбор для компонентов Vue. Но есть и следующие недостатки:

  • Ты должен бытьdataвходящийstyles
  • вы должны использоватьstyles.localClassNameимпортировать глобальное имя класса
  • Если есть другие имена глобальных классов, вы должны собрать их вместе
  • Если вы хотите привязаться к значению свойства компонента, даже если имя локального класса совпадает с именем свойства, вы должны указать его явно

Для компонента кнопки выше используйтеvue-css-modulesназад:

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">
    点我
  </button>
</template>

<script>
  import CSSModules from 'vue-css-modules'
  import styles from './button.css'

  export default {
    mixins: [CSSModules(styles)],
    props: { mini: Boolean }
  }
</script>

Сейчас:

  • ты не должен бытьdataвходящийstyles, но вmixinsвходящийstyles🌝
  • вы можете следоватьstyles.localClassNameпопрощаться
  • Поместите имя локального класса вstyleNameатрибут, имя глобального класса помещается вclassАтрибуты, много регуляризации
  • Имя локального класса связано с атрибутом того же имена, просто плюс его впереди.:модификатор

модификатор

@button

<button styleName="@button">按钮</button>

Это эквивалентно:

<button styleName="button" data-component-button="true">按钮</button>

Это позволяет вам сбросить стиль компонента извне:

.form [data-component-button] {
  font-size: 20px;
}

$type

<button styleName="$type">按钮</button>

Это эквивалентно:

<button :styleName="type">按钮</button>

:mini

<button styleName=":mini">按钮</button>

Это эквивалентно:

<button :styleName="mini ? 'mini' : ''">按钮</button>

disabled=isDisabled

<button styleName="disabled=isDisabled">按钮</button>

Это эквивалентно:

<button :styleName="isDisabled ? 'disabled' : ''">按钮</button>

инструкции

Использовать в шаблоне Vue

Импорт модулей CSS вне шаблона

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">
    点我
  </button>
</template>

<script>
  import CSSModules from 'vue-css-modules'
  import styles from './button.css'

  export default {
    mixins: [CSSModules(styles)],
    props: { mini: Boolean }
  }
</script>

Используйте модули CSS внутри шаблонов

<template>
  <button
    class="global-button-class-name"
    styleName="button :mini">
    点我
  </button>
</template>

<script>
  import CSSModules from 'vue-css-modules'

  export default {
    mixins: [CSSModules()],
    props: { mini: Boolean }
  }
</script>

<style module>
  .button {
    font-size: 16px;
  }
  .mini {
    font-size: 12px;
  }
</style>

Использование в Vue JSX

import CSSModules from 'vue-css-modules'
import styles from './button.css'

export default {
  mixins: [CSSModules(styles)],
  props: { mini: Boolean },
  render() {
    return (
      <button styleName="@button :mini">点我</button>
    )
  }
}

Использование в функции рендеринга Vue

import CSSModules from 'vue-css-modules'
import styles from './button.css'

export default {
  mixins: [CSSModules(styles)],
  props: { mini: Boolean },
  render(h) {
    return h('button', {
      styleName: '@button :mini'
    }, '点我')
  }
}

Принцип реализации

vue-css-modulesзарегистрированbeforeCreateХук, в котором перехватывается функция рендеринга компонента. Для параметров, переданных в функцию рендеринга, он будет проанализированdataилиdata.attrsсерединаstyleNameгенерирует строку имени глобального класса и прикрепляет ее кdata.staticClassпосле значения.

Гитхаб:vue-css-modules