# Mixins

# Fundamentos

Mixins distribuem funcionalidades reutilizáveis ​​para componentes Vue. Um objeto mixin pode conter quaisquer opções de componente. Quando um componente usa um mixin, todas as opções do mixin serão "misturadas" com as opções do próprio componente.

Exemplo:

// define um objeto mixin
const myMixin = {
  created() {
    this.hello()
  },
  methods: {
    hello() {
      console.log('olá do mixin!')
    }
  }
}

// definir um aplicativo que usa este mixin
const app = Vue.createApp({
  mixins: [myMixin]
})

app.mount('#mixins-basic') // => "olá do mixin!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Mesclagem de Opções

Quando um mixin e o próprio componente contêm opções se sobrepondo, elas serão "mescladas" usando estratégias apropriadas.

For example, each mixin can have its own data function. Each of them will be called, with the returned objects being merged. Properties from the component's own data will take priority in cases of conflicts.

const myMixin = {
  data() {
    return {
      message: 'olá',
      foo: 'abc'
    }
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  data() {
    return {
      message: 'Tchau',
      bar: 'def'
    }
  },
  created() {
    console.log(this.$data) // => { message: "Tchau", foo: "abc", bar: "def" }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Gatilhos de funções com o mesmo nome são mesclados em um Array para que todos sejam chamados. Os gatilhos do Mixin serão chamados antes dos próprios gatilhos do componente.

const myMixin = {
  created() {
    console.log('gatilho do mixin chamado')
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  created() {
    console.log('gatilho do componente chamado')
  }
})

// => "gatilho do mixin chamado"
// => "gatilho do componente chamado"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Opções que esperam valores em objeto, por exemplo methods, components e directives, serão mescladas no mesmo objeto. As opções do componente terão prioridade quando houver chaves conflitantes nestes objetos:

const myMixin = {
  methods: {
    foo() {
      console.log('foo')
    },
    conflicting() {
      console.log('do mixin')
    }
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  methods: {
    bar() {
      console.log('bar')
    },
    conflicting() {
      console.log('de si mesmo')
    }
  }
})

const vm = app.mount('#mixins-basic')

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "de si mesmo"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# Mixin Global

Você também pode aplicar um mixin globalmente para um aplicativo Vue:

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

// injetar um manipulador para a opção personalizada `myOption`
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

app.mount('#mixins-global') // => "Olá!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Use com cuidado! Depois de aplicar um mixin globalmente, ele afetará cada instância de componente criada posteriormente no aplicativo fornecido (por exemplo, componentes filhos):

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

// injetar um manipulador para a opção personalizada `myOption`
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

// adicione myOption também ao componente filho
app.component('test-component', {
  myOption: 'Olá do componente!'
})

app.mount('#mixins-global')

// => "Olá!"
// => "Olá do componente"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Na maioria dos casos, você só deve usá-lo para manipulação de opções personalizadas, conforme demonstrado no exemplo acima. Também é uma boa ideia entregá-los como Plugins para evitar aplicação duplicada.

# Estratégias de Mesclagem de Opções Personalizadas

Quando as opções personalizadas são mescladas, elas usam a estratégia padrão que substitui o valor existente. Se você deseja que uma opção personalizada seja mesclada usando uma lógica personalizada, você precisa anexar uma função à app.config.optionMergeStrategies:

const app = Vue.createApp({})

app.config.optionMergeStrategies.customOption = (toVal, fromVal) => {
  // retorna valorMesclado (mergedVal)
}
1
2
3
4
5

A estratégia de mesclagem recebe o valor dessa opção definida nas instâncias pai e filho como o primeiro e segundo argumentos, respectivamente. Vamos tentar verificar o que temos nesses parâmetros quando usamos um mixin:

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

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

app.mixin({
  custom: 'Tchau!',
  created() {
    console.log(this.$options.custom) // => "Olá!"
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Como você pode ver, no console temos toVal e fromVal impresso primeiro no mixin e depois no app. Nós sempre retornamos fromVal se existir, é por isso que this.$options.custom está configurado para hello! no final. Vamos tentar mudar uma estratégia para sempre retornar um valor da instância filha:

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

app.config.optionMergeStrategies.custom = (toVal, fromVal) => toVal || fromVal

app.mixin({
  custom: 'Tchau!',
  created() {
    console.log(this.$options.custom) // => "Tchau!"
  }
})
1
2
3
4
5
6
7
8
9
10
11
12

# Desvantagens

No Vue 2, os mixins eram a principal ferramenta para abstrair partes da lógica de componentes em blocos reutilizáveis. No entanto, eles têm alguns problemas:

  • Mixins são propensos à conflitos: como as propriedades de cada mixin são mescladas no mesmo componente, você ainda precisa conhecer todos os outros mixins para evitar conflitos de nome de propriedade e para depuração.

  • Properties seem to appear from nowhere: If a component uses multiple mixins it isn't necessarily obvious which properties came from which mixin.

  • Reutilização é limitada: não podemos passar nenhum parâmetro ao mixin para alterar sua lógica, o que reduz sua flexibilidade em termos de abstração da lógica.

Para resolver esses problemas, adicionamos uma nova maneira de organizar o código por questões lógicas: A API de Composição.