Vue.js инициализирует пользовательский компонент только один раз и использует его в качестве основы для нескольких представлений

Я создал компонент vue на основе MapBox, который ограничен в инициализации до того, как он будет стоить денег, и это совершенно нормально. Но я хочу уменьшить количество повторных инициализаций моего компонента карты ради них и себя. Вот почему я подумал, можно ли один раз определить компонент, передать некоторые свойства, а затем обрабатывать состояние через vuex.

Прямо сейчас мне пришлось бы импортировать свой компонент и добавить данные следующим образом:

<Map
  :sources = "geoData.sources"
  :layers = "geoData.layers"
  :mapOptions = "mapOptions"
  :componentOptions = "{ drawingEnabled: toggleMapDrawing, activeLayers: activeMapLayers, activeMarkerGroups: [] }"
  @loaded = "onMapLoaded" @selectedMarkers = "onSelectedObjects"/>

За componentOptions наблюдают, поэтому компонент соответствующим образом меняет свое состояние. Мои идеи/подходы до сих пор были следующими:

  1. Я подумал о добавлении приведенного выше фрагмента в корневой файл vue, но это не поможет, так как я хочу динамически, а не статически размещать компонент карты перед остальным содержимым страницы.
  2. Передача визуализированного компонента vue в переменную и добавление его позже было бы слишком хакерским, если это вообще возможно.
  3. Используя слоты, но из того, что я видел в документах, невозможно использовать компонент с слотами из родительского компонента в таком дочернем элементе.
  4. Лучшая идея, которая пришла мне в голову, заключалась в том, чтобы определить фактическую переменную MapBox (которая, я полагаю, запускает API для инициализации), а затем сохранить ее глобально, используя хранилище или что-то в этом роде. Но так как это немедленно добавит компонент к элементу DOM, который будет указан в параметрах, поэтому мне также нужно будет как-то его сохранить.

Инициализация карты происходит в смонтированном хуке компонента и выглядит так:

const baseOptions = {
  accessToken: process.env.MAPBOX_TOKEN,
  container: 'map',
  style: process.env.MAPBOX_STYLE_URL,
  minZoom: 10,
  maxZoom: 20,
  zoom: 13,
  bearing: 150,
  pitch: 50
}
this.map = new mapboxgl.Map(Object.assign(baseOptions, this.mapOptions))
if (!this.map) { throw new Error('Could not create map. Make sure the token is valid.') }

Я могу ошибаться, может быть, есть лучший способ, или, может быть, вся эта идея может быть мусором, но, надеюсь, это не так. Также обратите внимание, что я не использую модуль vue-mapbox, потому что он больше не поддерживается.

Буду благодарен за любые идеи и подсказки :)

Если я правильно понимаю это после быстрого чтения; вы хотите, чтобы компонент карты загружался один раз и оставался статичным до конца жизненного цикла вашего приложения? Вы не будете менять переданные реквизиты после его первой инициализации?

Muhammad Ammar 21.03.2022 10:02

@Fanoflix Я хочу изменить переданную опору после первой инициализации. Как я уже сказал, переданный реквизит componentOptions отслеживается внутри компонента для обработки состояния...

Blade 21.03.2022 10:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
43
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы могу используете <KeepAlive>, встроенный компонент, доступный как в Vue2 (документы), так и в Vue3 (документы).

По сути, это гарантирует, что компонент с тегом keep-alive будет mounted только один раз. Таким образом, в вашем случае вы можете разместить карту где угодно, и карта будет инициализирована только один раз в своем mounted хуке.

Если вам нужно использовать момент, когда ваша карта, так сказать, «сфокусирована» или «активирована», вы можете использовать хуки activated и deactivated.

Почему вы не можете использовать KeepAlive.

Есть очевидное и логичное ограничение. Пока родитель активен и смонтирован, дочерние компоненты компонента, которые поддерживаются активными, останутся активными. Но если родитель компонента поддержки активности размонтируется, то все файлы дети также будут демонтированы, даже если их оставили в живых. Это все очень очевидно, но мне просто захотелось указать на это.

Решение

Итак, в вашем случае использования вы хотите, чтобы компонент (компонент <Map>) был глобально сохранен после его первой инициализации. Я предлагаю вам кэшировать сам элемент карты и хранить его в хранилище. Затем на каждом хуке компонента <Map>onBeforeMount (Composition API) или beforeMount (Options API) вручную проверьте, кэширован ли элемент, если да, то вставьте кэшированную карту из хранилища, в противном случае инициализируйте карту.

Да, это звучит как правильный подход. Я могу реализовать компонент как синглтон. Это не звучит как слишком хакерский способ, я обязательно попробую, спасибо!

Blade 21.03.2022 18:03

Другие вопросы по теме