search
HomeWeb Front-endCSS TutorialHow the Vue Composition API Replaces Vue Mixins

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!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Next Level CSS Styling for CursorsNext Level CSS Styling for CursorsApr 23, 2025 am 11:04 AM

Custom cursors with CSS are great, but we can take things to the next level with JavaScript. Using JavaScript, we can transition between cursor states, place dynamic text within the cursor, apply complex animations, and apply filters.

Worlds Collide: Keyframe Collision Detection Using Style QueriesWorlds Collide: Keyframe Collision Detection Using Style QueriesApr 23, 2025 am 10:42 AM

Interactive CSS animations with elements ricocheting off each other seem more plausible in 2025. While it’s unnecessary to implement Pong in CSS, the increasing flexibility and power of CSS reinforce Lee's suspicion that one day it will be a

Using CSS backdrop-filter for UI EffectsUsing CSS backdrop-filter for UI EffectsApr 23, 2025 am 10:20 AM

Tips and tricks on utilizing the CSS backdrop-filter property to style user interfaces. You’ll learn how to layer backdrop filters among multiple elements, and integrate them with other CSS graphical effects to create elaborate designs.

SMIL on?SMIL on?Apr 23, 2025 am 09:57 AM

Well, it turns out that SVG's built-in animation features were never deprecated as planned. Sure, CSS and JavaScript are more than capable of carrying the load, but it's good to know that SMIL is not dead in the water as previously

'Pretty' is in the eye of the beholder'Pretty' is in the eye of the beholderApr 23, 2025 am 09:40 AM

Yay, let's jump for text-wrap: pretty landing in Safari Technology Preview! But beware that it's different from how it works in Chromium browsers.

CSS-Tricks Chronicles XLIIICSS-Tricks Chronicles XLIIIApr 23, 2025 am 09:35 AM

This CSS-Tricks update highlights significant progress in the Almanac, recent podcast appearances, a new CSS counters guide, and the addition of several new authors contributing valuable content.

Tailwind's @apply Feature is Better Than it SoundsTailwind's @apply Feature is Better Than it SoundsApr 23, 2025 am 09:23 AM

Most of the time, people showcase Tailwind's @apply feature with one of Tailwind's single-property utilities (which changes a single CSS declaration). When showcased this way, @apply doesn't sound promising at all. So obvio

Feeling Like I Have No Release: A Journey Towards Sane DeploymentsFeeling Like I Have No Release: A Journey Towards Sane DeploymentsApr 23, 2025 am 09:19 AM

Deploying like an idiot comes down to a mismatch between the tools you use to deploy and the reward in complexity reduced versus complexity added.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

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

Hot Tools

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version