I used to think that mixins merge with components first, that is, if the content of mixins conflicts with components, the components prevail. Such a case does exist, but the policies specified by VUE are more detailed. The following are the merge strategies corresponding to each case

basic

When a component uses a mixin, all mixin options are mixed into the component’s own options

// define a mixin object
const myMixin = {
  created() {
    this.hello()
  },
  methods: {
    hello() {
      console.log('hello from mixin! ')}}}// define an app that uses this mixin
const app = Vue.createApp({
  mixins: [myMixin]
})

app.mount('#mixins-basic') // => "hello from mixin!"
Copy the code

Option merge strategy

The options referred to here are data methods and lifecycle hook functions, which take different merge strategies

  • likedata,methods,components,directivesSuch items are merged into the same object, and the component’s conflicts prevail
const myMixin = {
  data() {
    return {
      message: 'hello'.foo: 'abc'}}}const app = Vue.createApp({
  mixins: [myMixin],
  data() {
    return {
      message: 'goodbye'.bar: 'def'}},created() {
    console.log(this.$data) // => { message: "goodbye", foo: "abc", bar: "def" }}})Copy the code
const myMixin = {
  methods: {
    foo() {
      console.log('foo')},conflicting() {
      console.log('from mixin')}}}const app = Vue.createApp({
  mixins: [myMixin],
  methods: {
    bar() {
      console.log('bar')},conflicting() {
      console.log('from self')}}})const vm = app.mount('#mixins-basic')

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
Copy the code
  • If there are hooks with the same name, they are merged together into an array and called one by one, and the mixin hook function is called first
const myMixin = {
  created() {
    console.log('mixin hook called')}}const app = Vue.createApp({
  mixins: [myMixin],
  created() {
    console.log('component hook called')}})// => "mixin hook called"
// => "component hook called"
Copy the code

Global blending and customization options

const app = Vue.createApp({
  myOption: 'hello! '
})

// inject a handler for `myOption` custom option
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

app.mount('#mixins-global') // => "hello!"
Copy the code

In the above code, we create a custom option globally, and then mix it globally, but note that this affects all the child components of the app:

const app = Vue.createApp({
  myOption: 'hello! '
})

// inject a handler for `myOption` custom option
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

// add myOption also to child component
app.component('test-component', {
  myOption: 'hello from component! '
})

app.mount('#mixins-global')

// => "hello!"
// => "hello from component!"
Copy the code

As we can see, this is not a simple substitution for the custom option, but a separate call, of course we can also make our own merge strategy:

const app = Vue.createApp({})

app.config.optionMergeStrategies.customOption = (toVal, fromVal) = > {
  // return mergedVal
}
Copy the code

The merge policy takes two parameters, one is the value of the specified item in the parent instance and the child instance, so we can see what to print when using mixins:

const app = Vue.createApp({
  custom: 'hello! '
})

app.config.optionMergeStrategies.custom = (toVal, fromVal) = > {
  console.log(fromVal, toVal)
  // => "goodbye!" , undefined
  // => "hello", "goodbye!"
  return fromVal || toVal
}

app.mixin({
  custom: 'goodbye! '.created() {
    console.log(this.$options.custom) // => "hello!"}})Copy the code

You can see the first print from mixin, and then print from app.

Matters needing attention

  • Mixins are prone to conflicts, and you need to make sure you don’t have conflicting property names to avoid conflicts, which can create an additional burden
  • Reusability is limited because mixins cannot accept parameters, so the logic is written and inflexible

So the official recommendation is to use the Composition Api to organize logic

Refer to the official documentation: Mixin