preface

Vue framework now basically has occupied the front half of the country, Vue’s data-driven and componentization ideas are deeply rooted in people’s minds. Vue family bucket may be a lot of friends are familiar with, in the work is also more handy. However, I believe that there are still many partners who do not know or have not used the usage of Mixin in Vue today. Or some partners will also use Mixin when they see a Mixin folder when they take over other people’s Vue projects, but they are always in a state of cloud and fog. Today, we will talk about Mixin, and try not to make confusion in the future.

1. What is Mixin?

In order to use an object or tool, we must first understand what it is so that we can adapt it to the situation.

In fact, Mixin is not Vue exclusive, it can be said that it is an idea, also can be said that it is mixed with the meaning, in many development frameworks have implemented Mixin(mixed), we mainly explain here is Vue Mixin.

Same old rule — official documents first.

Official explanation:

Mixins provide a very flexible way to distribute reusable functionality in Vue components. A mixin object can contain any component option. When a component uses mixin, all mixin options are “blended” into the component’s own options.

Official explanations are often obscure because they have to be professional and accurate.

We can say what a Mixin in Vue is in our own easy-to-understand terms.

Folk explanation:

Extract the common logic or configuration of a component and mix it into the component itself when needed. This reduces code redundancy and makes maintenance easier.

It is important to note here that you are extracting logic or configuration, not HTML code and CSS code. In fact, we can also change the idea, mixin is the component of the component, Vue componentization makes our code more reusable, so there are repeated parts between components, we use mixin to pull out again.

2. The difference between Mixin and Vuex?

The above point says that mixins are a function of pulling away from the common part. In Vue, Vuex state management seems to be doing just that, pulling data out of the way that might be shared between components. The two seem to be the same, but there are subtle differences as follows:

  • Vuex common state management. If one component changes some data in Vuex, all other components that reference that data in Vuex also change.
  • The data and methods in mixins are independent of each other, and components do not affect each other when used.

3. How to use it?

Now that we know the concept of mixins, how do we use them? That’s what we’re focusing on.

3.1 Preparations

Our mixin was then demonstrated in the scaffolding project for vue2.x.

Initialize one of the simplest projects with vue-CLI:

3.1 a mixin definition

Defining a mixin is also very simple. It is just an object that can contain some common configurations of Vue components, such as Data, methods, created, and so on.

Create a new mixin folder in our project SRC directory, and then create the index.js file that will hold our mixin code.

The code is as follows:

// src/mixin/index.js
export const mixins = {
  data() {
    return {};
  },
  computed: {},
  created() {},
  mounted() {},
  methods: {},
};
Copy the code

As you can see, our mixins are very simple, mainly containing a common logical structure for Vue components.

Now let’s simply write something in mixin as follows:

Export const mixins = {data() {return {MSG: "I am a pig ",}; }, computed: {}, created() {console.log(" I'm a created lifecycle function in mixins "); }, mounted() {console.log(" I am a mixin mounted lifecycle function "); }, methods: {clickMe() {console.log(" I'm a clickin in mixin "); ,}}};Copy the code

3.2 Local mixing

Once our public mixins are defined, the most important thing is how to use them. According to different business scenarios, we can divide into two types: local mixing and global mixing. As the name suggests, local mixing is similar to component loading on demand, in that we introduce it in the component chapter when we need to use the code in mixins. Global mixins mean I can use mixins in any component of my project.

Introducing mixins into components is also very simple, so let’s revamp the app.vue component a bit.

The code is as follows:

// src/App.vue <template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png" /> <button @click="clickMe"> </button> </div> </template> <script> import {mixins} from "./mixin/index"; Export default {name: "App", mixins: [mixins], Components: {}, created(){console.log(" Component calls minxi data ",this.msg); }, mounted(){console.log(" I am the component's mounted life cycle function ")}}; </script>Copy the code

The effect is as follows:

Introducing mixins in the previous code is also very simple, using the mixins properties vue provides us: mixins:[mixins].

From the above code and effects we can get the following points:

  • The lifecycle functions in mixins are executed in conjunction with the component lifecycle functions.
  • Data in mixins is also available in components.
  • Methods in mixins can be called directly from within components.
  • Lifecycle functions are executed in the order in which they are merged: first in the mixin, then in the component.

Question posed:

Here we ask the question: if one component changes the data in a mixin, will another component that references a mixin be affected?

The answer is no!

We can try this:

Create a new demo component in the Components folder under SRC as follows:

Vue <template> <div>mixin: {{MSG}}</div> </template> <script> import {mixins} from ".. /mixin/index"; export default { mixins: [mixins], }; </script>Copy the code

Then add the Demo component to the app.vue component as follows:

<template> <div id="app"> <img Alt ="Vue logo" SRC ="./assets/logo.png" / </button> <demo></ div> </template> <script> import {mixins} from "./mixin/index"; import demo from "./components/demo.vue"; Export default {name: "App", mixins: [mixins], Components: {demo}, created() {console.log(" Component call minxi data ", this.msg); }, mounted() {console.log(" I am the component's mounted lifecycle function "); }, methods: {changeMsg() {this.msg = "changeMsg "; Console. log(" changed MSG :", this.msg); ,}}}; </script>Copy the code

Code explanation:

  • We introduced mixins in the Demo component and used MSG data from mixins.
  • Mixins are also introduced in app.vue, and click events are set to change MSG
  • Click the button to change MSG and see if the demo component displays any changes.

The effect is as follows:

You can see that after we change MSG in the app.vue component, the demo component shows no change, so here we conclude that mixins in different components are independent of each other!

3.3 Global Mixing

In the previous point we used mixins to import them in the component where they were needed, or we can register them globally so we can use them directly in any component.

Modify main.js as follows:

import Vue from "vue";
import App from "./App.vue";
import { mixins } from "./mixin/index";
Vue.mixin(mixins);

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
}).$mount("#app");
Copy the code

Then comment out the code in app. vue that introduces mixins as follows:

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <button @click="clickMe">点击我</button>
    <button @click="changeMsg">更改mixin数据</button>
    <demo></demo>
  </div>
</template>

<script>
// import { mixins } from "./mixin/index";
import demo from "./components/demo.vue";
export default {
  name: "App",
  // mixins: [mixins],
  components: { demo },
  created() {
    console.log("组件调用minxi数据", this.msg);
  },
  mounted() {
    console.log("我是组件的mounted生命周期函数");
  },
  methods: {
    changeMsg() {
      this.msg = "我是变异的小猪课堂";
      console.log("更改后的msg:", this.msg);
    },
  },
};
</script>
Copy the code

The effect is as follows:

It can be found that there is no difference between local mixing and local mixing, which is the characteristic of global mixing.

While it’s convenient to do this, we don’t recommend it. Here’s the official quote:

Be careful with global mixin, as it affects each individually created Vue instance (including third-party components). In most cases, this should only apply to custom options, as in the example above. It is recommended to publish it as a plug-in to avoid repeated application mixing.

3.4 Merging Options

A closer look at the above column reveals one problem: there is no conflict between the names of properties or methods defined in mixins and those defined in components!

So we can’t help but think, what if there’s a naming conflict?

When you merge your code with Git, there are always conflicts. If there are conflicts, don’t be afraid to merge. The conflicts here are mainly divided into the following situations:

(1) Life cycle function

This is not exactly a conflict because the names of the lifecycle functions are fixed, and the default merge strategy is as follows:

  • Executing the code in the mixin lifecycle function first, and then executing the code inside the component is a good example.

(2) Data conflict

When the data in the mixin conflicts with the data in the component, the data in the component overwrites the data in the mixin.

var mixin = {
  data: function () {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}

new Vue({
  mixins: [mixin],
  data: function () {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created: function () {
    console.log(this.$data)
    // => { message: "goodbye", foo: "abc", bar: "def" }
  }
})
Copy the code

As you can see, the final printed message is the value of message in the component, and the rest of the non-conflicting data is merged.

(3) Conflict of methods

It’s easy to run into this kind of conflict, because it’s easy to name a method, so here’s the official code:

var mixin = {
  methods: {
    foo: function () {
      console.log('foo')
    },
    conflicting: function () {
      console.log('from mixin')
    }
  }
}

var vm = new Vue({
  mixins: [mixin],
  methods: {
    bar: function () {
      console.log('bar')
    },
    conflicting: function () {
      console.log('from self')
    }
  }
})

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
Copy the code

The Conficting method is present in both the mixin and the component in the previous code, but the conflicting method is actually called when called in the component.

Of course, it’s ok if you want to customize the merge rules, but I don’t think it’s necessary, it doesn’t have to be that complicated in the project.

4. Advantages and disadvantages of mixins

From the above examples, there are many advantages to using mixins, but there are always two sides to all mixins. Here are some advantages and disadvantages for your reference:

4.1 the advantages

  • Improve code reuse
  • No need to pass state
  • Easy to maintain, only need to modify a place

4.2 disadvantages

  • Naming conflicts
  • Abusive words are difficult to maintain later
  • It’s not good to trace the source. It’s a little more difficult to troubleshoot the problem
  • Don’t easily duplicate code

conclusion

Mixins are both convenient and disastrous, so there are a lot of times when it’s not recommended to overuse them, but there are situations where it’s perfectly appropriate to use them, and it’s up to you. So a lot of times we need to consider whether to use common components or mixins.