@lodbrok

Как во Vue добавить класс без $style.название_класса?

Всем привет. Подскажите возможно ли добавить класс таким образом:
<template>
  <div>
    <div :class="test1">test1</div>
    <div :class="test2">test2</div>
  </div>
</template>

<script>

export default {
  name: 'Test'
}
</script>

<style module>
  .test1 {
    color: red;
  }
  .test2 {
    color: green;
  }
</style>

вместо этого:
<template>
  <div>
    <div :class="$style.test1">test1</div>
    <div :class="$style.test2">test2</div>
  </div>
</template>

<script>

export default {
  name: 'Test'
}
</script>

<style module>
  .test1 {
    color: red;
  }
  .test2 {
    color: green;
  }
</style>

И чтобы при этом названия классов оставались модульными:
5e0e07f27cdc4662271183.png
  • Вопрос задан
  • 348 просмотров
Решения вопроса 1
bingo347
@bingo347
Crazy on performance...
Модульный CSS - это не особенность vue, это особенность связки css-loader + vue-loader для webpack. Роль css-loader тут в замене имен классов (а так же имен keyframes и прочих внутренних штук, но не имен тегов и не id) на хэш от пути к файлу и оригинального имени класса, а так же предоставлении объекта с маппингом оригинального имени класса в сопоставленный ему хэш. А роль vue-loader в добавлении миксина с beforeCreate хуком прокидывающим объект маппинга в this.$style
Из документации css-loader можно узнать, что любой селектор или его часть можно обернуть в конструкцию :global() чтобы указанные имена классов не переименовывались.

style[scoped]
да с этим познакомился, но тогда не будет модульности у классов
Данная штука работает на уровне самого компилятора vue и она дает модульность за счет добавления атрибута вида v-1234567 (где 1234567 - хэш от содержимого файла .vue) ко всем тегам и добавления селектора по атрибуту. Поставленную задачу это действительно решает, оставляя оригинальные классы и работая даже на имена тегов, но ценной более медленных селекторов по атрибуту.
Почему нельзя было решить эту задачу добавлением доп класса, как это сделано в svelte например, с которого Эван Ю почти полностью своровал дизайн... Это известно лишь самому Эвану, который впрочем очень часто единолично принимает не самые оптимальные по производительности решения, когда не умеет сделать нормально.

Еще одним решением будет немного покодить. Указанный в вопросе фрагмент шаблона
<template>
  <div>
    <div :class="test1">test1</div>
    <div :class="test2">test2</div>
  </div>
</template>
будет искать поля с ключами test1 и test2 в this, а значит их вполне можно туда переложить в beforeCreate хуке из this.$style, например так:
const mixin = {
  beforeCreate() {
    const applyClassNames = () => Object.keys(this.$style).forEach(className => {
      this[className] = this.$style[className];
    });
    if(!this.$style) {
      // наш миксин может оказаться раньше миксина лоадера
      Object.defineProperty(this, '$style', {
        enumerable: true,
        configurable: true,
        get() {},
        set: $style => {
          Object.defineProperty(this, '$style', {
            enumerable: true,
            configurable: true,
            writable: true,
            value: $style
          };
          applyClassNames();
        }
      });
      return;
    }
    applyClassNames();
  }
};
export default {
  mixins: [mixin],
  // ...
};
Правда минусом подхода будет то, что все имена классов окажутся непосредственно в this компонента, что черевато конфликтами.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@lodbrok Автор вопроса
Нашел так же еще два решения, не знаю насколько они правильные, может кто-то подскажет, но возможно кому-то пригодится.
1)Код конфига vue.config.js:
module.exports = {
  configureWebpack: {
    resolve: {
      modules: ['src', 'node_modules'],
    },
  },
  css: {
    requireModuleExtension: false,
    loaderOptions: {
      css: {
        modules: {
          localIdentName: '[path]-[local]-[hash:4]'
        },
      }
    }
  }
}

Код компонента:
<template>
  <div :class="qqq">test1</div>
</template>

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

export default {
  name: 'Test',
  data: function () {
    return {
      ...styles
    }
  },
}
</script>

Название класса в итоге:
5e0f1c8f40d00022016063.png
2)Конфиг vue.config.js остается таким же, но необходимо установить данный пакет Vue CSS Modules.
Код компонента:
<template>
  <div styleName="qqq">test1</div>
</template>

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

export default {
  name: 'Test',
  mixins: [CSSModules(styles)],
}
</script>

Название класса:
5e0f216e9ae54699224484.png
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы