How the Vue Composition API Replaces Vue Mixins
Sharing code between Vue components? If you are familiar with Vue 2, you may have used mixin to achieve this. But the new Composition API (now available as a plugin for Vue 2 and is an upcoming feature of Vue 3) provides a better solution.
This article will explore the shortcomings of mixin and understand how the Composition API overcomes these shortcomings and makes Vue applications more scalable.
Brief description of Mixin
Let's quickly review the mixin mode, as it is crucial to what we'll cover in the next section.
Typically, the Vue component is defined by a JavaScript object that has various properties that represent the functions we need to implement - such as data, methods, computed properties, etc.
// MyComponent.js export default { data: () => ({ myDataProperty: null }), methods: { myMethod () { ... } } // ... }
When we want to share the same properties between components, we can extract the common properties into a separate module:
// MyMixin.js export default { data: () => ({ mySharedDataProperty: null }), methods: { mySharedMethod () { ... } } }
Now we can add this mixin to any component that uses it by assigning it to the mixin configuration property. At runtime, Vue merges the component's properties with any added mixin.
// ConsumingComponent.js import MyMixin from "./MyMixin.js"; export default { mixins: [MyMixin], data: () => ({ myLocalDataProperty: null }), methods: { myLocalMethod () { ... } } }
For this particular example, the component definition used by the runtime is as follows:
export default { data: () => ({ mySharedDataProperty: null, myLocalDataProperty: null }), methods: { mySharedMethod () { ... }, myLocalMethod () { ... } } }
Mixin is considered "harmful"
As early as mid-2016, Dan Abramov wrote “Mixins Considered Harmful”, in which he believed using mixins in React components to reuse logic is an anti-pattern, advocating avoiding them.
Unfortunately, the shortcomings he mentioned about React mixin also apply to Vue. Before we understand how the Composition API overcomes these shortcomings, let's take a look at these shortcomings.
Naming conflict
We see how mixin mode merges two objects at runtime. What happens if they all share a property with the same name?
const mixin = { data: () => ({ myProp: null }) } export default { mixins: [mixin], data: () => ({ // The same name! myProp: null }) }
This is where the merger strategy comes into play. This is a set of rules to determine what happens when a component contains multiple options with the same name.
The default (but configurable) merge policy of Vue components stipulates that local options will override mixin options. But there are exceptions. For example, if we have multiple life cycle hooks of the same type, these hooks will be added to the hook array and all hooks will be called sequentially.
Even if we don't encounter any actual errors, it can be increasingly difficult to write code when dealing with named properties between multiple components and mixins. This is especially difficult once a third-party mixin as npm package and its named properties that may cause conflicts.
Implicit dependency
There is no hierarchical relationship between mixin and the components that use it. This means that the component can use data properties defined in the mixin (e.g. mySharedDataProperty), but the mixin can also use it assuming data properties defined in the component (e.g. myLocalDataProperty). This is common when using mixin to share input validation. The mixin may expect the component to have an input value which will use in its own validate method.
But this can cause problems. What happens if we want to refactor the component later and change the name of the variables required by the mixin? We won't notice any issues from the components. The code inspector will not find it either. We will only see errors at runtime.
Now imagine a component that contains many mixins. Can we refactor local data properties, or will it break the mixin? Which mixin? We have to search for all mixins manually to know.
Migrate from mixin
Dan's article provides alternatives to mixin, including advanced components, utility methods, and some other component combination patterns.
While Vue is similar to React in many ways, the alternative pattern he suggests doesn't convert well to Vue. So, although this post was written in mid-2016, Vue developers have been enduring mixin issues since then.
Until now. The disadvantages of mixin are one of the main motivational factors behind the Composition API. Before you understand how it overcomes the mixin problem, let's take a quick look at how it works.
Composition API crash course
The key idea of the Composition API is that instead of defining the functions of components (such as states, methods, computed properties, etc.) as object properties, they are defined as JavaScript variables returned from the new setup function.
Here is a classic example of a Vue 2 component defined using the Composition API, which defines a "counter" function:
//Counter.vue export default { data: () => ({ count: 0 }), methods: { increment() { this.count ; } }, computed: { double () { return this.count * 2; } } }
Here are the exact same components defined using the Composition API.
// Counter.vue import { ref, calculated } from "vue"; export default { setup() { const count = ref(0); const double = computed(() => count.value * 2) function increment() { count.value ; } return { count, double, Increment } } }
You will first notice that we imported the ref function, which allows us to define a responsive variable that has almost the same function as a data variable. The same is true for the computered function.
The increment method is not responsive, so it can be declared as a normal JavaScript function. Note that we need to change the subproperty value to change the value of the count responsive variable. This is because responsive variables created with ref need to be objects to maintain their responsiveness when passed.
It is best to consult the Vue Composition API documentation for a detailed understanding of how ref works.
After defining these functions, we return them from the setup function. There is no difference in the functions of the above two components. All we did was using the alternative API.
Tip: The Composition API will be the core feature of Vue 3, but you can also use the NPM plugin @vue/composition-api in Vue 2.
Code Extraction
The first obvious advantage of the Composition API is its ease of extracting logic.
Let's use the Composition API to refactor the components defined above so that the functionality we define is in the JavaScript module useCounter. (The prefix using "use" as the function description is the naming convention of the Composition API.)
// useCounter.js import { ref, calculated } from "vue"; export default function () { const count = ref(0); const double = computed(() => count.value * 2) function increment() { count.value ; } return { count, double, Increment } }
Code reuse
To use this function in a component, we simply import the module into the component file and call it (note that import is a function). This will return the variables we define, which we can then return from the setup function.
// MyComponent.js import useCounter from "./useCounter.js"; export default { setup() { const { count, double, increment } = useCounter(); return { count, double, Increment } } }
At first, this seems a bit lengthy and meaningless, but let's see how this pattern overcomes the mixin problem we've seen before.
Naming conflict...resolved!
We have seen before that mixin can use properties that may be of the same name as those in the use component, or even more concealedly as those in other mixin used by the use component.
This problem does not exist in the Composition API because we need to explicitly name any state or method returned from the compositing function:
export default { setup () { const { someVar1, someMethod1 } = useCompFunction1(); const { someVar2, someMethod2 } = useCompFunction2(); return { someVar1, someMethod1, someVar2, someMethod2 } } }
Naming conflicts will be resolved in the same way as any other JavaScript variable.
Implicit dependency...resolved!
We have also seen before that mixin can use data properties defined on components, which makes the code fragile and difficult to understand.
Combination functions can also call local variables defined in components. However, the difference is that this variable must now be passed explicitly to the combined function.
import useCompFunction from "./useCompFunction"; export default { setup () { // A local value that needs to be used for the combination function const myLocalVal = ref(0); // It must be explicitly passed as a parameter const { ... } = useCompFunction(myLocalVal); } }
Summarize
The mixin mode looks very safe on the surface. However, because it increases the vulnerability of the code and the way it masks the ability to understand functions, sharing code by merging objects becomes an anti-pattern.
The cleverest thing about the Composition API is that it allows Vue to rely on security measures built into native JavaScript to share code, such as passing variables to functions and module systems.
Does this mean that the Composition API is superior to Vue's classic API in every way? No. In most cases, you can stick to the classic API. However, if you plan to reuse your code, the Composition API is undoubtedly a better choice.
The above is the detailed content of How the Vue Composition API Replaces Vue Mixins. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics





It's out! Congrats to the Vue team for getting it done, I know it was a massive effort and a long time coming. All new docs, as well.

With the recent climb of Bitcoin’s price over 20k $USD, and to it recently breaking 30k, I thought it’s worth taking a deep dive back into creating Ethereum

I had someone write in with this very legit question. Lea just blogged about how you can get valid CSS properties themselves from the browser. That's like this.

I'd say "website" fits better than "mobile app" but I like this framing from Max Lynch:

The other day, I spotted this particularly lovely bit from Corey Ginnivan’s website where a collection of cards stack on top of one another as you scroll.

If we need to show documentation to the user directly in the WordPress editor, what is the best way to do it?

There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing

Questions about purple slash areas in Flex layouts When using Flex layouts, you may encounter some confusing phenomena, such as in the developer tools (d...
