Answer the question
In order to leave comments, you need to log in
How to add a class without $style.class_name in Vue?
Hello. Can you tell me if it's possible to add a class like this:
<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>
Answer the question
In order to leave comments, you need to log in
Modular CSS is not a feature of vue, it's a feature of the css-loader + vue-loader bundle for webpack. The role of css-loader here is to replace the class names (as well as the names of keyframes and other internal things, but not the names of tags and not id) with a hash of the file path and the original class name, as well as providing an object with a mapping of the original class name in its associated hash. And the role of vue-loader is to add a mixin with a beforeCreate hook that passes the mapping object to this.$style
From the css-loader documentation, you can learn that any selector or part of it can be wrapped in a :global() construct so that the specified class names are not renamed.
style[scoped]
Yes, I got acquainted with this, but then there will be no modularity in classesThis thing works at the level of the vue compiler itself and it gives modularity by adding an attribute of the form v-1234567 (where 1234567 is a hash of the contents of the .vue file) to all tags and adding an attribute selector. This really solves the problem, leaving the original classes and working even on tag names, but at the cost of slower attribute selectors.
<template>
<div>
<div :class="test1">test1</div>
<div :class="test2">test2</div>
</div>
</template>
will look for fields with the keys test1 and test2 in this, which means that they can be moved there in the beforeCreate hook from this.$style, like this: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],
// ...
};
True, the minus of the approach is that all class names will be directly in the component's this, which is fraught with conflicts.
I also found two more solutions, I don’t know how correct they are, maybe someone will tell you, but maybe it will come in handy for someone.
1) vue.config.js config code:
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>
<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>
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question