Reputation: 3773
For each component with prefix mycomponent-
I would like to add a class with the name of the component. I don't want to have to modify the component in order to do this.
My first thought was to use mixins and somehow add the class in beforeCreate
but I haven't managed to add classes dynamically without using the template.
Do I have to use $el.classList.add(this.$options.name)
in beforeUpdate
or similar? Is there some more Vue-ish way to do it?
Upvotes: 0
Views: 228
Reputation: 90013
Here it is, wrapped up as plugin:
const addComponentNameAsClass = {
install(Vue, options) {
const fn = Vue.prototype.$mount;
Vue.prototype.$mount = function() {
fn.apply(this, arguments);
if (this.$options._componentTag?.startsWith("mycomponent-")) {
this.$el.classList.add(this.$options._componentTag);
}
}
}
}
Vue.use(addComponentNameAsClass);
// that's all you need
// see it working:
['a', 'b', 'foo', 'whatever'].forEach(type => {
Vue.component('mycomponent-' + type, {
template: '<div><slot /></div>'
})
});
new Vue({
el: '#app'
})
[class^="mycomponent-"] {
border: 1px solid;
margin-bottom: 4px;
padding: 1rem;
}
.mycomponent-a {
border-color: red;
}
.mycomponent-b {
border-color: blue;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app">
<mycomponent-a>I should get a red border.</mycomponent-a>
<mycomponent-b>I should get a blue one.</mycomponent-b>
<mycomponent-foo>bar</mycomponent-foo>
<mycomponent-whatever>Meh.</mycomponent-whatever>
</div>
Notes:
_
Vue does not guarantee they'll still be there in the next major version update. But, on the other hand, the name
of the component is not saved anywhere else (other than $options._componentTag
).<MycomponentA></MycomponentA>
. However, you can swiftly get around it by running the value of $options._componentTag
through a helper function (e.g: kebabCase
from lodash
).
kebab-case
, you'll have run the value passed to .classList.add()
through kebabCase
, as well). Otherwise, <MycomponentA>
will add MycomponentA
class and <mycomponent-a>
will add mycomponent-a
class, for obvious reasons.Ref. "Vue-ish way": whatever the end goal of applying this "component" class is, chances are it can be achieved cleaner.
The very idea of placing classes denominating component type doesn't feel Vue-ish at all.
It feels WordPress-ish and Angular-ish. To me, at least.
Upvotes: 1