# Примеси
# Основы
Примеси (mixins) — инструмент повторного использования кода в компонентах Vue. Объект примеси может содержать любые опции компонентов. При использовании примеси в компоненте все её опции «подмешиваются» к опциям компонента.
Пример:
// определяем объект примеси
const myMixin = {
created() {
this.hello()
},
methods: {
hello() {
console.log('привет из примеси!')
}
}
}
// определяем приложение, которое использует примесь
const app = Vue.createApp({
mixins: [myMixin]
})
app.mount('#mixins-basic') // => "привет из примеси!"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Слияние опций
Если примесь и компонент содержат одинаковые опции, то они будут объединяться определённым образом.
Например, объект data
примеси претерпевает рекурсивное слияние с объектом data
компонента, который имеет приоритет в случаях конфликтов.
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" }
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Функции хуков объединяются в массив, чтобы все они вызывались. При этом хуки примеси будут вызываться перед хуками в самом компоненте.
const myMixin = {
created() {
console.log('вызван хук из примеси')
}
}
const app = Vue.createApp({
mixins: [myMixin],
created() {
console.log('вызван хук из компонента')
}
})
// => "вызван хук из примеси"
// => "вызван хук из компонента"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Опции, значения которых в виде объектов, такие как methods
, components
и directives
будут объединены. В случае конфликта, приоритет имеют опции компонента:
const myMixin = {
methods: {
foo() {
console.log('foo')
},
conflicting() {
console.log('из примеси')
}
}
}
const app = Vue.createApp({
mixins: [myMixin],
methods: {
bar() {
console.log('bar')
},
conflicting() {
console.log('из самого компонента')
}
}
})
const vm = app.mount('#mixins-basic')
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "из самого компонента"
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
# Глобальные примеси
Примесь может быть применена глобально для Vue приложения:
const app = Vue.createApp({
myOption: 'hello!'
})
// внедрение обработчика для пользовательской опции `myOption`
app.mixin({
created() {
const myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
app.mount('#mixins-global') // => "hello!"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Используйте данную возможность ОСТОРОЖНО! Глобальная примесь окажет влияние на все экземпляры компонентов, создаваемые в дальнейшем в этом приложении (например, во всех дочерних компонентах):
const app = Vue.createApp({
myOption: 'привет!'
})
// внедрение обработчика для пользовательской опции `myOption`
app.mixin({
created() {
const myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
// добавляем myOption также в дочерний компонент
app.component('test-component', {
myOption: 'привет из компонента!'
})
app.mount('#mixins-global')
// => "привет!"
// => "привет из компонента!"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
В большинстве случаев их стоит использовать только для обработки пользовательских опций, как на примере выше. Неплохой идеей будет их оформление в виде плагинов, что позволит избежать дублирования кода.
# Пользовательские стратегии слияния опций
По умолчанию, при слиянии пользовательских опций, применяется стратегия, которая просто заменяет одни значения другими. Если необходимо использовать пользовательскую логику при слиянии, можно переопределить функцию в app.config.optionMergeStrategies
:
const app = Vue.createApp({})
app.config.optionMergeStrategies.customOption = (toVal, fromVal) => {
// возвращаем объединённое значение
}
2
3
4
5
Стратегия слияния получает значения опции из родительского и дочернего экземпляров, в качестве первого и второго аргументов соответственно. Посмотрим, что приходит в этих параметрах при использовании примеси:
const app = Vue.createApp({
custom: 'привет!'
})
app.config.optionMergeStrategies.custom = (toVal, fromVal) => {
console.log(fromVal, toVal)
// => "пока!", undefined
// => "привет!", "пока!"
return fromVal || toVal
}
app.mixin({
custom: 'пока!',
created() {
console.log(this.$options.custom) // => "привет!"
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Как видно, в консоли выводятся значения toVal
и fromVal
сначала из примеси, а затем из app
. Сейчас всегда возвращается fromVal
при наличии, поэтому this.$options.custom
в результате будет со значением привет!
. Изменим стратегию слияния на «всегда возвращать значение дочернего экземпляра»:
const app = Vue.createApp({
custom: 'привет!'
})
app.config.optionMergeStrategies.custom = (toVal, fromVal) => toVal || fromVal
app.mixin({
custom: 'пока!',
created() {
console.log(this.$options.custom) // => "пока!"
}
})
2
3
4
5
6
7
8
9
10
11
12
# Предостережения
Во Vue 2 примеси были основным инструментов для абстрагирования части логики компонентов в многократно переиспользуемые куски. Но у них есть несколько проблем:
Примеси приводят к конфликтам: поскольку свойства каждой примеси объединяются в одном компоненте, всё равно потребуется знать обо всех свойствах для избежания конфликта имён свойств и в целях отладки.
Возможность переиспользования ограничена: примесям нет возможности передавать какие-либо параметры для управления логикой её работы, что снижает гибкость с точки зрения абстрагированной логики.
Для решения этих проблем был добавлен новый способ организации кода: Composition API.