by yugasun from yugasun.com/post/there-ma…Эта статья может быть воспроизведена полностью, но должны быть сохранены первоначальный автор и источник.
В реальном процессе разработки, когда проект становится больше, а компонентов становится все больше и больше, мы часто сталкиваемся с проблемой: многие компоненты будут иметь некоторые общие черты.props,dataа такжеmethodsи другие объявления, а также некоторые частные и уникальные объявления самого компонента, поэтому можем ли мы уточнить и наследовать, как наследование классов? Конечно, это возможно, здесь доступны два основных API.extendsа такжеmixinsреализовать. Эти два API взаимозаменяемы, разница только в том,extendsСвойства обычно принимают один объект-компонент, в то время какmixinsСвойство принимает массив объектов-компонентов. Они взаимозаменяемы, если наследуют только один компонент. Поскольку я развиваюсь, я привык использоватьmixins, поэтому во всех примерах в этой статье используетсяmixinsреализовать.
mixins
Давайте взглянем на официальное введение:
mixinsOptions принимает массив объектов примесей. Эти объекты экземпляра миксина могут содержать параметры, такие как обычные объекты экземпляра, и в конечном итоге они будут объединены с использованием той же логики объединения параметров в Vue.extend() . Пример: если ваш миксин содержит хук, а сам компонент create имеет один, будут вызваны две функции.
Простое понимание состоит в том, что все конфигурации свойств в экземпляре Vue можно настроить с помощьюmixinsРеализовать наследование.
Простой пример выглядит следующим образом:
var mixin = {
created: function () { console.log(1) }
}
var vm = new Vue({
created: function () { console.log(2) },
mixins: [mixin]
})
// => 1
// => 2
Дело 1
Допустим есть такое требование:在某个组件渲染后向服务器端发送一个请求,进行打点ок, скоро мы подумалиmountedПерехватите функцию, а затем быстро реализуйте требования, код выглядит следующим образом:
export default {
name: 'comp1',
// ...
mounted() {
console.log('Component comp1 mounted');
}
// ...
}
Затем в один прекрасный день спрос становится某几个 组件需要进行打点Ладно, мы проделали еще одну жестокую операцию, скопировали приведенный выше код в каждый управляемый компонент и быстро уладили требования. Но кошмар только начался.Через несколько дней требования снова изменились.Помимо необходимости управлять после рендеринга компонента,его еще нужноcreatedТочка позже.....此种场景是不是像极了爱情, перед лицом реальности мы всегда постоянно уступаем, и в конце концов мы неохотно выполнили требования.
Оглядываясь назад и думая об этом спокойно, на самом деле, это управление является очень распространенным требованием. Если мы начнем с нуля, мы определенно выберем реализацию по наследству, а не слепо любя, о нет, слепо копируя и вставляя. потому что у нас естьmixins, нужно написать только один раз, доступно везде. Итак, давайте проделаем все сначала, сначала создайтеsrc/minins/log.jsдокумент:
export default {
created() {
console.log(`Component ${this.$options.name} created.`);
},
mounted() {
console.log(`Component ${this.$options.name} mounted.`);
},
};
Затем используйте его в любом компоненте, который вам нужен:
import logMixin from '@/mixins/log';
export default {
name: 'comp1',
mixins: [logMixin],
// ...
}
После некоторой модификации вы обнаружите, что девушка-менеджер по продукту тоже может быть такой очаровательной, вы снова начали верить в любовь...
Запускаем проект, открываем консоль и выводим следующее:
Component comp1 created.
Component comp2 created.
Случай 2
Вышеприведенное требование относится к управлению компонентами.Теперь мы добавили новое требование, и нам нужно добавить общий метод к некоторым компонентам.sayHelloприбытьmethods, и она вызывается после рендеринга компонента, но только некоторые из перечисленных выше компонентов нуждаются в добавлении этой функции.Хотя это только часть компонента, но их сотни(夸张手法,切勿模仿). Услышав это, ты молча оттолкнул от себя девушку-продуктовика и отказался:对不起,我已经不相信爱情了. В этот момент чей-то голос тихо прошептал:你还可以相信的!.
Хорошо, тогда я заставлю тебя снова в это поверить. Сначала добавьте файлsrc/mixins/func.js:
export default {
mounted() {
this.sayHello();
},
methods: {
sayHello() {
console.log('产品妹子,你好美!');
},
},
};
Затем просто импортируйте его в необходимые компоненты:
import logMixin from '@/mixins/log';
import funcMixin from '@/mixins/func';
export default {
name: 'comp1',
mixins: [logMixin, funcMixin],
// ...
}
Запускаем проект, открываем консоль и выводим следующее:
Component comp1 created.
Component comp2 created.
Component comp1 mounted.
产品妹子,你好美!
Component comp2 mounted.
Случай 3
Ну, наконец-то вы можете счастливо бегать на закате с девушкой-продуктом. Вдруг однажды,组件渲染后打点,成了公司的规范, то есть всеми компонентами, которые вы написали, нужно управлять, а продакт-девушка беспомощно посмотрела на вас и сказала:这不是我想要的结果,是你做的太优秀,被公司提上了日程,写入了编码规范...но реальность такова,你总想逃,却逃不掉......
На самом деле, вы все еще можете сбежать.Vue.mixinСказать.
Глобальная регистрация миксина влияет на каждый экземпляр Vue, созданный после регистрации. Авторы плагинов могут использовать примеси для внедрения пользовательского поведения в компоненты.Не рекомендуется для использования в коде приложения.
Разве это не та любовь, которую вы искали? Таким образом, вы удалили ранее введенныйlogMixin, а потом молча во входном файле (src/main.js) написал признание в любви:
//...
Vue.mixin({
created() {
console.log(`Component ${this.$options.name} created from 全局打点`);
},
mounted() {
console.log(`Component ${this.$options.name} mounted from 全局打点`);
},
});
// new Vue....
Запускаем проект, открываем консоль и выводим следующее:
Component undefined created from 全局打点
Component App created from 全局打点
Component Index created from 全局打点
Component router-link created from 全局打点
Component comp1 created from 全局打点
Component comp1 created.
Component comp2 created from 全局打点
Component comp2 created.
Component comp3 created from 全局打点
Component router-link mounted from 全局打点
Component comp1 mounted from 全局打点
Component comp1 mounted.
产品妹子,你好美!
Component comp2 mounted from 全局打点
Component comp2 mounted.
Component comp3 mounted from 全局打点
Component Index mounted from 全局打点
Component App mounted from 全局打点
Component undefined mounted from 全局打点
Вы найдете все компоненты Vue, внедренные с помощью RBI.
Принципиальный анализ
фактическиmixinsОн очень прост в использовании, но принцип, лежащий в его основе, все же стоит изучить:
- Зачем
mixinsПосле того, как функция хука выполняется последовательно, а не заменяется? - Зачем
mixinsпосле себяdataСвойства над свойствами миксина?
Чтобы ответить на поставленные выше вопросы, мы должны начать с исходного кода vue.
Vue инициализируетсяmixinКогда для разных атрибутов принятая стратегия отличается, код инициализации находится в файлеsrc/core/global-api.js, следующим образом:
import { mergeOptions } from '../util/index'
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
Vue.options = mergeOptions(Vue.options, mixin)
}
}
вы найдете это черезmergeOptionsфункция для выполнения слияния, она находится в файлеsrc/core/util/options.js, его исходный код выглядит следующим образом:
/**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*/
export function mergeOptions (
parent: Object,
child: Object,
vm?: Component
): Object {
// 省略不必要代码
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key)
}
}
function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
return options
}
Эту функцию легко понять, и что она, вероятно, делает, так этоchildсвойства объединены вparent, разные атрибуты используют разные стратегии, которые определены вstratsна объекте.
давайте сначала посмотрим生命周期函数Стратегия слияния, код выглядит следующим образом:
/**
* Hooks and param attributes are merged as arrays.
*/
function mergeHook (
parentVal: ?Array<Function>,
childVal: ?Function | ?Array<Function>
): ?Array<Function> {
return childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal
}
Можно обнаружить, что функции жизненного цикла экземпляра Vue, наконец, назначаются массиву, аmixinsМассив объединен в . Именно поэтому компонентыmixinsСледующие функции жизненного цикла являются причиной последовательного исполнения.
Также посмотрите наdataСтратегия слияния:
/**
* Helper that recursively merges two data objects together.
*/
function mergeData (to: Object, from: ?Object): Object {
let key, toVal, fromVal
for (key in from) {
toVal = to[key]
fromVal = from[key]
if (!hasOwn(to, key)) {
set(to, key, fromVal)
} else if (isObject(toVal) && isObject(fromVal)) {
mergeData(toVal, fromVal)
}
}
return to
}
Этот процесс представляет собой слияние свойств объекта, ноtoприоритет выше, чемfrom, поэтому мы делаем компонентmixinsВремя, само собойdataприоритет над миксиномdataимущество, то есть еслиmixinsКогда и нейтральные, и сами содержат одно и то же свойство, значение свойства примеси не добавляется к текущему компоненту.
Заинтересованные студенты могут также изучить стратегию смешивания других атрибутов.Исходный код находится вsrc/core/util/options.js, тоже хорошо понятно.
Суммировать
Чем проще вещь, тем больше палка о двух концах.Вы должны обращать на это внимание при реальном использовании, особенно глобальное микширование, которое приведет к снижению производительности. Вы можете написать больше, обобщить больше и найти наиболее подходящие привычки использования.Рекомендуется прочитать исходный код известных проектов с открытым исходным кодом, и вы получите больше навыков от предшественников.