Mixins
Mixins
Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options.
Basic example
Let's say we have a couple of different components whose job it is to toggle a state boolean, a modal and a tooltip. These tooltips and modals don't have a lot in common except for that functionality: they don't look the same, they're not used the same, but the logic is similar.
//modal
{
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: { AppChild }
}
//tooltip
{
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: { AppChild }
}
We could extract the logic here and create a mixin that can be reused:
const toggle = {
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
}
}
const Modal = {
mixins: [toggle],
components: { AppChild }
};
const Tooltip = {
mixins: [toggle],
components: { AppChild }
};
Avoid mixing everything
Mixins are very sexy and is easy to fall in the trap of extracting everything to a mixin. There are cases where all that we need is just another component.
- Modal A
<template>
<div>
<div @toggleShow="click">Toggle</div>
<ModalA v-if="isShowing" />
</div>
</template>
export default {
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: { ModalA }
}
- Modal B
<template>
<div>
<div @toggleShow="click">Toggle</div>
<ModalB v-if="isShowing" />
</div>
</template>
export default {
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: { ModalB }
}
At first sight it seems that we should create a mixin. But even the template for both are very similar. In this case a parent component fits better.
- Base Modal
<template>
<div>
<div @toggleShow="click">Toggle</div>
<slot v-if="isShowing" />
</div>
</template>
export default {
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
}
- Modal A
<template>
<BaseModal>
<ModalA />
</BaseModal>
</template>
export default {
components: { BaseModal, ModalA }
}
- Modal B
<template>
<BaseModal>
<ModalB />
</BaseModal>
</template>
export default {
components: { BaseModal, ModalB }
}