Sometimes, you'll face situations where an existing component almost fits your new requirements but not quite. Some other times, you'll notice that different components actually have quite a lot in common, but also diverge too much in some respects.
Application design choices are often very situational, and there aren't many solutions that you can blindly apply, no matter what. For example, splitting components means introducing some level of duplication and breaking the DRY principle, while extending or combining existing components can lead to bloat (for example, too many properties on a single component) or introduce leaky abstractions and more trouble down the line.
Vue.js mixins (not to be confused with TypeScript mixins!) provide a way for us to share/reuse functionality between Vue components. Mixins are inherently functional; they make it possible for us to encapsulate a single feature/functionality and reuse it across different components in the application.
With Vue.js, mixin objects may contain any Vue component option. When a mixin is used in a component, all of the options that are defined by the mixin are merged with the host component's options.
Let's go through a few examples to make this more tractable.
Here is a very simple mixin that will log a message whenever a component that uses it is created:
const loggingMixin = { created() { console.log("I'm the logging mixin"); } };
As we mentioned previously, mixin is a simple object that includes Vue component options. In this example, we've used the created lifecycle hook.
Using this mixin in a component is as simple as adding it to the mixins option's array:
Vue.component('foo', { template: '<div>bar</div>', mixins: [ loggingMixin, ], });
Any code that's declared in mixins has priority over the code of the host component. This means that methods such as the created lifecycle method will execute first.
In the case of conflicting data or conflicting object properties (for example, prop with the same name declared on both), then the component wins over the mixins. The option merging rules are described here: https://vuejs.org/v2/guide/mixins.html#Option-Merging.
Vue.mixin(...). Be careful, however: declaring a global mixin has an impact on all the components, including third-party ones. This can cause surprises if you're not careful, so it is clearly not a recommended practice.
One limitation of Vue.js mixins to be aware of is the fact that they can't rely on or use the state that's held by another mixin/component, or share its state with them. This is actually a good characteristic since it prevents us from mixing concerns and needlessly introducing strong coupling.
An important downside of using mixins is that they introduce magic and, thus, indirection. Once mixins have been introduced to a project, it becomes less obvious where data/logic is held/coming from.
You can find a few more example mixins in this book's sample code, under Chapter09/mixins/index-01-mixin-basic.html.