[JavaScript, Программирование, VueJS] Как работают функции provide и inject во Vue 3?
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Релиз третьей версии фреймворка Vue предоставил разработчикам доработанный API для манипуляции состоянием приложения. Во Vue 3 были дополнены инструменты для реализации паттерна Dependency Injection. Использование этого паттерна вместе с доработанной системой реактивности позволяет разработчикам отказаться от использования VueX, MobX или любой другой библиотеки для управления стейтом приложения, и получить больший контроль над архитектурой приложения. Если все же решите отказаться от стейт менеджмента с помощью библиотек, то следует помнить, что
С большой силой приходит большая ответственность.
Появление provide и inject во VueДля инъекции зависимостей в компонентах Vue можно было использовать свойства provide и inject начиная ещё с версии 2.2.0. Но тогда они были частью объявления компонентов, и принцип их работы был интуитивно понятен: когда Vue находит в компоненте provide, то он ищет среди предков компонента нужные значение заданные свойством inject.
Как работает Vue Dependency InjectionПереход на функциональную основу в третьей версииТретья мажорная версия фреймворка расширила этот синтаксис и позволила использовать функции provide и inject для инъекции зависимостей. Особенность этих функций состоит в том, что они работают, как ожидается, только во время синхронного исполнения метода setup или синхронного исполнения методов жизненного цикла компонента. При этом соблюдается строгая иерархия зависимостей, т.е. у компонентов потомков есть доступ только к зависимостям от предков, а не все получают доступ к глобальным зависимостям. Проиллюстрировано на картинке выше.
// …
const injectFunction = () => inject('key2', 'value2');
export default defineComponent({
setup() {
inject('key', 'value'); // работает
injectFunction(); // тоже работает
setTimeout(injectFunction); // а это не работает
},
methods: {
// вызов метода при браузерном событии (e.g. click) не сработает, а в методах жизненного цикла будет работать
injectFromMethod() {
inject('key', 'value');
},
},
});
Как устроены inject и provide под капотомВнутрненний принцип работы этих функций не является очевидным. По крайней мере, мне он не показался очевидным, поэтому я копался в исходниках, чтоб во всем разобраться. Можно было б предположить, что функции provide и inject могут как-то знать в каком контексте вызваны, но это невозможно. Единственный способ передавать контекст, в котором вызвана функция в js это ее аргументы или this, но мы не используем ни то, ни другое. На самом деле контекст и не передается. Нам и не нужно его передавать. Vue просто хранит данные компонента, обработка которого происходит в данный момент, в отдельной переменной уровня видимости модуля. Просто представьте следующий код:
// …
let currentInstance = null
function renderComponent(componentInstance) {
currentInstance = componentInstance;
componentInstance.setup();
// do rest rendering logic
// also set currentInstance to be componentInstance whenever lifecycle hook is called
}
export function provide(key, value) {
if (!currentInstance.provides) {
currentInstance.provides = Object.create(currentInstance.parent.provides);
}
currentInstance.provides[key] = value;
}
export function inject(key) {
return currentInstance.parent.provides[key];
}
Выше наведен очень утрированный пример, без обработки многих крайних случаев (нулевые значения, асинхронный setup, дебаг логи, и т.д.), но в целом он дает нам возможность понять, как Vue DI работает на самом деле. Для хранения информации о том какие данные обеспечены (provided) используется обычное прототипное наследование, а для того, чтоб инъецировать зависимость мы просто получаем её из свойства provides компонента, обработка которого происходит в данный момент.Мне подход с изменением значения переменной компонента, который обрабатывается в данный момент, показался хрупким и не идиоматичным, но тем не менее на практике он показывает себя достаточно надежным. Все приложения, в которых я использовал provide и inject, работали стабильно и проблем не возникало.Много ключевого функционала Vue опирается на возможность получить компонент, который обрабатывается в данный момент. Более того Vue предоставляет возможность разработчикам самим получить этот компонент с помощью экспортированной функции getCurrentInstance.Как это можно использовать?Зависимости, предоставленные с помощью provide можно получить только в дочерних компонентах, но не в компоненте который их предоставляет.
// …
// такой код выведет предупреждения, а значение переменной value будет равно undefined
export default defineComponent({
setup() {
provide('key', 'value');
const value = inject('key');
},
});
Что если существует гипотетическая ситуация, в которой нам понадобилось получить их в компоненте, который их предоставил? Давайте напишем реализацию функции, которая сможет инъецировать зависимости, в том числе предоставленные компонентом, который обрабатывается в данный момент.
// …
// Такой код будет работать как нам нужно, т.е. значение переменной value будет получено
// из свойства provide данного компонента
export const injectFromCurrent = (key: string) => {
const componentInstance = getCurrentInstance() as any;
const componentProvides = componentInstance?.provides || {};
if (!(key in componentProvides)) {
console.warn(`injection ${key} not found.`);
return undefined;
}
const dependency = componentProvides[key];
return dependency;
};
// …
export default defineComponent({
setup() {
provide('key', 'value');
const value = injectFromCurrent('key');
},
});
Хотя в целом это будет полезно разработчикам плагинов к Vue или для на самом деле продвинутых юз-кейсов, чем большинству разработчиков приложений.ВыводыVue предоставляет разработчикам обширный функционал для эффективной разработки приложений и уже обошёл React по количеству звёзд на Github, что свидетельствует, о его популярности среди разработчиков. Использование 3 версии ещё не так распространено, хотя последняя версия фреймворка предоставляет много интересного функционала. Знание об их внутреннем устройстве может быть полезно как при решении задач связанных непосредственно связанных с Vue, так и при похожих фич у себя в приложении, не использующем какой-либо фреймворк.
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Java] Работа с БД с помощью JAVA и JDBC
- [Программирование, Венчурные инвестиции, Развитие стартапа, Образование за рубежом, Бизнес-модели] Перевод Курса по стартапам и бизнесу от Стэнфордского Университета. Лекция №4. Создание продукта, общение с клиентами… (перевод)
- [JavaScript, Разработка игр, Логические игры] Путеводитель разработчика по Garbo-боту
- [Разработка веб-сайтов, Программирование, Symfony] Главные причины, почему мы разрабатываем веб-приложения на Symfony (перевод)
- [Поисковые технологии, Программирование, NoSQL, Администрирование баз данных] Знакомство с ArangoDB
- [JavaScript, Программирование] Взлом JavaScript с помощью JavaScript (перевод)
- [Программирование, .NET] Создание пакета NuGet для библиотеки с платформозависимым API
- [Программирование, Машинное обучение, Учебный процесс в IT, Карьера в IT-индустрии] И в науку, и в индустрию. Магистерские программы при поддержке JetBrains
- [Информационная безопасность, Программирование] Что под капотом у R-Vision Threat Intelligence Platform?
- [Системное администрирование, Программирование, IT-инфраструктура, Apache] Apache Pulsar как основа для системы очередей
Теги для поиска: #_javascript, #_programmirovanie (Программирование), #_vuejs, #_vuejs, #_provide, #_inject, #_internals, #_javascript, #_programmirovanie (
Программирование
), #_vuejs
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:33
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Релиз третьей версии фреймворка Vue предоставил разработчикам доработанный API для манипуляции состоянием приложения. Во Vue 3 были дополнены инструменты для реализации паттерна Dependency Injection. Использование этого паттерна вместе с доработанной системой реактивности позволяет разработчикам отказаться от использования VueX, MobX или любой другой библиотеки для управления стейтом приложения, и получить больший контроль над архитектурой приложения. Если все же решите отказаться от стейт менеджмента с помощью библиотек, то следует помнить, что С большой силой приходит большая ответственность.
Как работает Vue Dependency InjectionПереход на функциональную основу в третьей версииТретья мажорная версия фреймворка расширила этот синтаксис и позволила использовать функции provide и inject для инъекции зависимостей. Особенность этих функций состоит в том, что они работают, как ожидается, только во время синхронного исполнения метода setup или синхронного исполнения методов жизненного цикла компонента. При этом соблюдается строгая иерархия зависимостей, т.е. у компонентов потомков есть доступ только к зависимостям от предков, а не все получают доступ к глобальным зависимостям. Проиллюстрировано на картинке выше. // …
const injectFunction = () => inject('key2', 'value2'); export default defineComponent({ setup() { inject('key', 'value'); // работает injectFunction(); // тоже работает setTimeout(injectFunction); // а это не работает }, methods: { // вызов метода при браузерном событии (e.g. click) не сработает, а в методах жизненного цикла будет работать injectFromMethod() { inject('key', 'value'); }, }, }); // …
let currentInstance = null function renderComponent(componentInstance) { currentInstance = componentInstance; componentInstance.setup(); // do rest rendering logic // also set currentInstance to be componentInstance whenever lifecycle hook is called } export function provide(key, value) { if (!currentInstance.provides) { currentInstance.provides = Object.create(currentInstance.parent.provides); } currentInstance.provides[key] = value; } export function inject(key) { return currentInstance.parent.provides[key]; } // …
// такой код выведет предупреждения, а значение переменной value будет равно undefined export default defineComponent({ setup() { provide('key', 'value'); const value = inject('key'); }, }); // …
// Такой код будет работать как нам нужно, т.е. значение переменной value будет получено // из свойства provide данного компонента export const injectFromCurrent = (key: string) => { const componentInstance = getCurrentInstance() as any; const componentProvides = componentInstance?.provides || {}; if (!(key in componentProvides)) { console.warn(`injection ${key} not found.`); return undefined; } const dependency = componentProvides[key]; return dependency; }; // … export default defineComponent({ setup() { provide('key', 'value'); const value = injectFromCurrent('key'); }, }); =========== Источник: habr.com =========== Похожие новости:
Программирование ), #_vuejs |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:33
Часовой пояс: UTC + 5