preloader

How to Manage Mixins in Vue.JS?

Vue Mixins are simple, yet quite flexible ways of reusing functionalities across multiple components. 
The name is self-explaining. All options from the mixin object are “mixed” with the component’s options to form the final options set. Mixins are part of the Vue 2 only, as they’re replaced by Composition API in Vue 3. 

The general recommendation is to use mixins when two or more components need to share reusable logic. 

const myMixin = { 
  data() { 
    return { 
      name: "Mixin", 
      blog: { 
        name: "Vue functionality sharing", 
        sources: { 
          docs: true 
        } 
      } 
    } 
  }, 
  computed: { 
    fullName() { 
      return "Vue " + this.name; 
    }, 
  }, 
} 

export { 
  myMixin, 
} 

mixin.js 

 <template> 
  <div>{ { fullName } }</div> 
</template>
<script> 
  import {myMixin} from "./mixin.js"; 

  export default { 
    mixins: [myMixin], 
    data() { 
      return { 
        name: "Component", 
        blog: { 
          name: "Vue functionality sharing - Mixins", 
          author: "Robert Molnar" 
        } 
      } 
    } 
  } 
</script> 

Component.vue 

When “Component” is added to the DOM, it will display “Vue Component” within the resulting HTML. 

Global Mixins 

Mixins are usually grouped by the “thing they provide”. Each of the groups should be in a separate file, so that only the necessary pieces are imported. Sometimes, depending on the project you’re working on, it can happen that all the components need to have some specific method.  

Instead of manually importing all the required mixins within all the components, there is a way to perform this “out of the box” – by using global mixins. 

 
Our general recommendation: add all global mixins before the initial component is rendered. 

const globalMixin = { 
  data() { 
    return { 
      name: "Global", 
      blog: { 
        sources: { 
          otherBlogs: true 
        } 
      } 
    } 
  }, 
} 

Vue.mixin(globalMixin); 

main.js 

Merging Options 

As you can see in the examples above, it might happen that mixins have overlapping options. In that case, the order of importing mixins is crucial. 

Merging non-conflicting options, like lifecycle hooks, watchers, etc., is done by simple chaining. The order of execution is the same as the order of importing. The last handler to be invoked is the one specified in the component itself. 

The objects returned by data option will be deeply merged into one with primitive values being overwritten. The order of merging is the same as the order of importing. The data object provided by the component has the greatest relevance. 

 
The data object of the component above will look like this: 

{ 
  name: "Component", 
  blog: { 
    "name": "Vue functionality sharing - Mixins", 
    "author": "Robert Molnar", 
    "sources": { 
      "docs": true, 
      "otherBlogs": true 
    } 
  } 
} 

The methods and computed values are simply overridden. 

This default merging strategy can be avoided by introducing a custom option merging logic. 

Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) { 
  // return mergedVal 
}

Conclusion 

In Vue mixins, options are merged by the default strategy, but there is a way to introduce a custom merging strategy. These are available in Vue 2 only, as Vue 3 provides Composition API.   

To conclude, these factors provide us with a tool that reduces the amount of code we have to write and maintain while improving readability. 

About Author

Robert Molnar is a coding connoisseur with over ten years of experience and a versatile skill set encompassing several programming languages and technologies. With his extensive knowledge of Vue.js, Angular, Java, Node.js, and more, he is a master of all trades in the realm of software development. Molnar’s passion for technology is evident in his notable projects, including NAQ Cyber, Fireside, and MedMatch, where he has left his indelible mark.

VueJS: Basic Change Detection

The latest generation of frontend frameworks brings us the possibility to take better care of users and provide them with the best possible user experience (UX). In order to do so, we ought to keep our users with the latest available data. A problem that arises is how to detect changes and display them in real-time. In the pool of many options, it is important to maintain the simplicity-flexibility ratio on the expected level. VueJS stands out as one of the simplest, yet quite flexible framework

Keeping the data updated

Providing users with top-quality UX requires a smooth change detection algorithm and seamless layout updates. Featuring two-way binding, VueJS provides us with high performance and easy data flow. Another thing being featured is virtual DOM – a smarter and more efficient little brother of the traditional HTML DOM.

How does this work?

One of the ways to keep the data updated everywhere is two-way data binding by using the v-model directive. Let’s explain how this works on a basic code example:

<div id=”app”>
  <input v-model=”myValue” type=”number”>
</div>
let vm = new Vue({
  data: {
    myValue: 1,
    myObject: {},
    myArray: []
  },
  methods: {
    changeValue() {
      this.myValue = 2;
    }
  }
})

The value in the input field will automatically be set to 1. If a user makes a change, it will be automatically propagated to the myValue property. When a changeValue method is invoked, the value of myValue property will be changed to 2, which will be immediately visible on the UI.

When the Vue instance is created, it automatically builds a virtual DOM tree based on the initially given data and dependent components. Each Vue instance has at least one component. If the data option of a Vue component is a plain JavaScript (JS) object, Vue will create appropriate getters and setters for all its properties. These properties are considered to be reactive, and their implicit simple getters and setters are part of the default Vue change detection algorithm. Any occurring change will invoke the setter function, which will eventually trigger the component to re-render and re-generate its virtual DOM, which will, in turn, through various diffing algorithms, update only the relevant part(s) of the HTML DOM.

When this isn’t working?

Unfortunately, there are cases when this approach isn’t the best. According to VueJS official documentation, Vue cannot detect deletion and addition which would mean that it is not possible to add new reactive properties to objects with simple assigning of value. Also, it is not possible to add new root-level reactive properties

//Neither of this will be reactive
this.myNewValue = 1; //new root-level property
this.myObject.someProperty = 1; //new nested object property
this.myObject[‘someProperty’] = 1; //new nested object property
this.myArray[0] = 1; //new nested array element

In order to make new reactive properties, we ought to use a method dedicated to such a purpose

Vue.set(object, property, value) 

Invocation of this method will make property reactive.

Each Vue instance also has $set method, which is syntactic sugar for the previously mentioned method
this.$set(object, property, value)

//All will make the property reactive
Vue.set(this.myObject, ‘someProperty’, 1);
this.$set(this.myObject, ‘someProperty’, 1);

When it comes to arrays, we should treat them as any other object. Instead of the property name, an element index needs to be provided

this.$set(this.myArray, 0, 1);

Of course, arrays have additional methods, like push, slice, splice… which will also make the magic happen.

If there is a need to assign multiple reactive properties, they can be added one-by-one using the explained process if all properties are known. On the other hand, when the set of new properties is unknown, it is recommended to use the universal approach:
Create a new object and replace the old one with it

//Object b holds all properties which should be added
this.myObject = Object.assign({}, this.myObject, b);

The reasons for replacement are following:

  1. Object.assign() and other similar methods will not invoke Vue.set() method, making all further changes irrelevant and ignored
  2. Replacement will not replace the value only, but the reference too, which will invoke component re-rendering
  3. If a “property of a property” has changed, this might not be detected

Combination of Vue.set and object replacement will also result in expected behavior

this.$set(this, ‘myObject’, Object.assign({}, this.myObject, b))

Conclusion

With current limitations, both from VueJS and Javascript itself, the safest way to ensure all changes are visible and detectable is to anticipate all possible properties in advance and declare them before Vue instance is created and use dedicated Vue methods to apply those changes, especially when there is a need to add a new property.
In addition to that, make sure that object-like values (objects, arrays, etc.) are always updated by using embedded reactive methods or by plain reference replacement.

The written is valid for Vue.js 2.

Comments16

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsa iste inventore rem Community Guidelines.

by Simon & Garfunkel
23 0 reply 3 days ago
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat a voluptatum voluptatibus ducimus mollitia hic quos, ad enim odit dolor architecto tempore, dolores libero perspiciatis, sapiente officia non incidunt doloremque?
by Simon & Garfunkel
23 0 reply 3 days ago
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat a voluptatum voluptatibus ducimus mollitia hic quos, ad enim odit dolor architecto tempore, dolores libero perspiciatis, sapiente officia non incidunt doloremque?
by Simon & Garfunkel
23 0 reply 3 days ago
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat a voluptatum voluptatibus ducimus mollitia hic quos, ad enim odit dolor architecto tempore, dolores libero perspiciatis, sapiente officia non incidunt doloremque?
by Simon & Garfunkel
23 0 reply 3 days ago
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus. Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat a voluptatum voluptatibus ducimus mollitia hic quos, ad enim odit dolor architecto tempore, dolores libero perspiciatis, sapiente officia non incidunt doloremque?