Reputation: 315
I have a component v-popup.vue
<template>
<div class="overlay">
<div class="popup">
<slot></slot>
</div>
</div>
</template>
and I want to style it from the parent, for example:
<template>
<v-popup class="custom-popup">
Popup content
</v-popup>
</template>
<style>
.custom-popup {
padding: 20px;
}
</style>
How can I configure v-popup.vue
component to make custom-popup
class to be automatically added to div.popup
, not div.overlay
?
Upvotes: 6
Views: 7588
Reputation: 340
In your v-popup.vue, you can do the following:
<template>
<div class="overlay">
<div :class="['popup', popupClass]">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
// Do the usual implementations here...
props: {
popupClass: ''
}
}
</script>
Then in your parent component, you can do the following:
<template>
<v-popup popup-class="custom-popup">
Popup content
</v-popup>
</template>
However, I am curious. Why not encapsulate this class inside v-popup.vue. I seldom use this design unless there will be another component sharing this class from the parent.
EDIT (per your last comment): You can use this link as a reference on how to use the $attr attribute: https://jsfiddle.net/changjoo_park/pzx08wp9/
So, in a sense, you can do the following, in your parent component
<template>
<v-popup popup-class="custom-popup" v-bind="$attrs">
Popup content
</v-popup>
</template>
In your v-popup component:
<template>
<div class="overlay">
<div :class="['popup', $attrs.popupClass]">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
// Do the usual implementations here...
}
</script>
So, no props implementations and the class is taken directly from the $attrs object. Hope this helps! You can read more about this usage here: https://v2.vuejs.org/v2/api/#vm-attrs
Upvotes: 3
Reputation: 63059
Using scoped styles (in both parent and child) is a good idea and will make this solution easier.
Instead of creating a new custom-popup
class, use a deep selector in the parent. This allows the parent to define extra styles for child components that use the same selector.
The deep selector looks like this: >>>
unless you're using a SCSS/SASS pre-processor. Then you use ::v-deep
instead.
<template>
<v-popup>
Popup content
</v-popup>
</template>
<style scoped>
>>> .popup {
padding: 20px;
}
/* If using SCSS/SASS, do this instead */
/*
::v-deep .popup {
padding: 20px;
}
*/
</style>
The child will use both its own .popup
class and the one from the parent.
If you didn't use scoped styles, it would quickly become a problem if you wanted to import the child in multiple parents and use different styles each time.
Upvotes: 6