В Vue есть еще два продвинутых статических метода mixin и extend.Далее давайте обсудим их соответствующие принципы и сценарии использования.
Письмо МИ:
принцип:
Давайте взглянем на введение официального сайта:
параметр: {Object} mixin
Применение:
Миксины также могут быть зарегистрированы глобально. Будьте предельно осторожны! Как только глобальный миксин будет использован, он повлияет на каждый последующий созданный экземпляр Vue. При правильном использовании это можно использовать для внедрения логики обработки для пользовательских параметров.
// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})
new Vue({
myOption: 'hello!'
})
// => "hello!"
Мы знаем, что объект параметра, переданный Vue.mixin, будет объединен с параметрами при инициализации экземпляра Vue.Ниже показано действие миксина в исходном коде Vue.
// src\core\global-api\mixin.js
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
this.options = mergeOptions(this.options, mixin)
return this
}
}
// src\core\instance\index.js
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
...
export default Vue
Тем не менее, примеси — это просто расширение объекта конфигурации, который мы передаем при инициализации нашего экземпляра Vue.
Как и в примере, написанном на официальном сайте выше, мы передаем объект конфигурации при выполнении метода Vue.mixin.В объекте есть созданная функция ловушки.Из исходного кода мы видим, что переданный объект в конечном итоге инициализируется экземпляр с нами.То есть параметры в new Vue(options) объединяются (через метод mergeOptions в исходном коде выше) и сохраняются в параметре.
используемые сцены:
Когда нам нужно внедрить некоторые методы, фильтры или хуки глобально, мы можем использовать примеси. Например, если мы хотим, чтобы у каждого экземпляра Vue был метод печати, мы можем сделать это:
Vue.mixin({
methods: {
print() {
console.log(`我是一个通过mixin注入的方法!`)
}
}
})
Или, если мы хотим отслеживать, на каком этапе какие компоненты загружаются, выгружаются и т.д., мы можем сделать это:
Vue.mixin({
mounted() {
console.log(`${this.$route.name} component mounted!`)
},
destroyed() {
console.log(`${this.$route.name} component destroyed!`)
}
})
Если мы не хотим смешивать эти параметры конфигурации для каждого экземпляра компонента, а только для отдельных компонентов, лучше не использовать миксины, это может повлиять на производительность наших компонентов.
Продлевать:
принцип:
Давайте взглянем на введение официального сайта:
параметр: {Object} options
Применение:
Используя базовый конструктор Vue, создайте «подкласс». Параметр — это объект, содержащий параметры компонента.
Опция data — это особый случай, и на нее нужно обратить внимание — в Vue.extend() она должна быть функцией.
data должен быть функцией, чтобы предотвратить загромождение данных каждого экземпляра и применение замыканий.
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
Давайте посмотрим на реализацию Vue.extend в исходном коде:
Vue.extend = function (extendOptions: Object): Function {
extendOptions = extendOptions || {}
const Super = this
const SuperId = Super.cid
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
if (cachedCtors[SuperId]) {
return cachedCtors[SuperId]
}
const name = extendOptions.name || Super.options.name
if (process.env.NODE_ENV !== 'production' && name) {
validateComponentName(name)
}
const Sub = function VueComponent (options) {
this._init(options)
}
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.cid = cid++
Sub.options = mergeOptions(
Super.options,
extendOptions
)
Sub['super'] = Super
// For props and computed properties, we define the proxy getters on
// the Vue instances at extension time, on the extended prototype. This
// avoids Object.defineProperty calls for each instance created.
if (Sub.options.props) {
initProps(Sub)
}
if (Sub.options.computed) {
initComputed(Sub)
}
// allow further extension/mixin/plugin usage
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use
// create asset registers, so extended classes
// can have their private assets too.
ASSET_TYPES.forEach(function (type) {
Sub[type] = Super[type]
})
// enable recursive self-lookup
if (name) {
Sub.options.components[name] = Sub
}
// keep a reference to the super options at extension time.
// later at instantiation we can check if Super's options have
// been updated.
Sub.superOptions = Super.options
Sub.extendOptions = extendOptions
Sub.sealedOptions = extend({}, Sub.options)
// cache constructor
cachedCtors[SuperId] = Sub
return Sub
}
}
Прежде всего, мы видим, что Sub, возвращаемый методом extend, на самом деле является конструктором и унаследован от Vue, а это означает, что метод extend возвращает подкласс Vue.
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Эти две строки кода на самом деле реализуют наследование Sub от Vue.
const Super = this
Итак, Super здесь относится к Vue.
Sub.options = mergeOptions(
Super.options,
extendOptions
)
Мы заметили, что входящие параметры конфигурации и исходные параметры Vue также объединены.
используемые сцены:
Когда нам не нужно смешивать какую-то конфигурацию глобально, например, мы хотим получить компонент. Мы можем использовать Vue.component() или Vue.extend().
const ChildVue = Vue.extend({
...options
})
new ChildVue({
...options
})
Обратите внимание, что расширение получает подкласс Vue, который является конструктором.
разница:
Mixin предназначен для смешивания опций класса Vue. Все объекты экземпляра Vue будут иметь смешанное поведение конфигурации.
Расширение заключается в создании подкласса, наследуемого от класса Vue, который влияет только на объект экземпляра этого подкласса и не влияет на сам класс Vue и объект экземпляра класса Vue..