1. Создайте компонент, который инициализирует нашу карту.

В шаблоне мы создаем контейнер для карты, который будет использоваться для монтирования объекта Карта, извлеченного из Google Maps API.

GoogleMapLoader.vue

Внутри части скрипта:

  • мы получаем реквизиты от родительского компонента, которые позволят нам установить карту Google:
  • MapConfig - объект конфигурации Google Maps
  • ApiKey - наш личный ключ API, требуемый Google Maps.

GoogleMapLoader.vue

  • мы устанавливаем начальные значения google и map равными нулю

  • на установленном хуке мы создаем экземпляр GoogleMapsApi и объекта Map из GoogleMapApi, и мы устанавливаем значения google и сопоставляем созданные экземпляры

Пока все хорошо, после этого мы можем продолжить добавление других объектов на карту (маркеры, полилинии и т. Д.) И использовать их как обычный компонент карты. Но мы хотим использовать наш компонент GoogleMapLoader только как загрузчик, который подготавливает карту, а не отображает что-либо на ней.

Для этого нам нужно разрешить родительскому компоненту, который будет использовать наш GoogleMapLoader, для доступа к this.google и this.map, которые установлены внутри компонента GoogleMapLoader. Вот где действительно сияют слоты с ограниченным диапазоном. Слоты с заданной областью позволяют нам предоставлять родительскому компоненту свойства, установленные в дочернем компоненте. Это может звучать как начало, но потерпите еще одну минуту.

2. Создайте компонент, который использует наш компонент инициализатора.

В шаблоне мы визуализируем компонент GoogleMapLoader и передаем реквизиты, необходимые для инициализации карты.

TravelMap.vue

На этом этапе наш тег скрипта будет выглядеть так, как показано ниже.

По-прежнему нет слотов с заданной областью действия, давайте добавим еще один.

3. Предоставьте родительскому компоненту доступ к свойствам Google и сопоставьте свойства, добавив слот с заданной областью действия.

Итак, наконец, мы можем добавить слот с ограниченной областью видимости, который будет выполнять эту работу и позволит нам получить доступ к свойствам дочернего компонента в родительском компоненте. Мы делаем это, добавляя тег ‹slot› в дочерний компонент и передавая свойства, которые мы хотим раскрыть (используя директиву v-bind или сокращенное обозначение: propName). Это не отличается от передачи свойств дочернему компоненту, но выполнение этого в теге ‹slot› меняет направление потока данных.

GoogleMapLoader.vue

Теперь, когда у нас есть слот в дочернем компоненте, нам нужно получать и использовать открытые реквизиты в родительском компоненте.

4. Получите открытые реквизиты в родительском компоненте с помощью атрибута slot-scope.

Чтобы получить реквизиты в родительском компоненте, мы объявляем элемент шаблона и используем атрибут slot-scope. Атрибут имеет доступ к объекту, несущему все свойства, предоставленные дочерним компонентом. Мы можем захватить объект целиком или разрушить этот объект и получить необходимые реквизиты. Перейдем ко второму варианту.

TravelMap.vue

После этого, даже если реквизиты Google и карты не существуют в области TravelMap, компонент имеет к ним доступ, и мы можем использовать их в шаблоне.

Да, хорошо, но зачем мне это делать, какой от всего этого толк?

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

5. Создайте фабричные компоненты для маркеров и полилиний.

Теперь, когда у нас есть готовая карта, мы создадим два фабричных компонента, которые будут использоваться для добавления элементов в TravelMap.

GoogleMapMarker.vue

GoogleMapLine.vue

  • оба они получают Google, из которого мы извлекаем требуемый объект (маркер или ломаную линию) и карту, которая дает ссылку на карту, на которой мы хотим разместить наш элемент.
  • каждый компонент ожидает также дополнительной опоры для создания соответствующего элемента
  • на установленном крючке мы создаем элемент (Маркер / Полилиния) и прикрепляем его к нашей карте, передавая свойство карты в конструктор объекта

6. Добавить элементы на карту

Теперь давайте воспользуемся нашими фабричными компонентами, чтобы добавить элементы на нашу карту.

Чтобы добавить элементы на нашу карту, мы визуализируем компонент factory и передаем объекты google и map.

Нам также необходимо предоставить данные, необходимые для самого элемента (в нашем случае объект-маркер с положением маркера и объект пути с координатами полилинии).

TravelMap.vue

В нашем скрипте нам нужно импортировать необходимые заводские компоненты и установить данные, которые будут передаваться маркерам и линиям.

Резюме

Вот и все. Создав все эти кусочки и фрагменты, мы теперь можем повторно использовать компонент GoogleMapLoader в качестве основы для всех наших карт, передавая разные шаблоны каждому из них. Представьте, что вам нужно создать еще одну карту с другими маркерами или просто маркерами без полилиний. Используя вышеуказанный шаблон, это становится очень просто, поскольку нам просто нужно передать различный контент в компонент GoogleMapLoader.

Этот шаблон строго не связан с Google Maps, его можно использовать с любой библиотекой для установки базового компонента и предоставления API библиотеки, который затем может быть использован в компоненте, вызвавшем базовый компонент.

Может возникнуть соблазн создать очень сложные решения на основе примера, но в какой-то момент мы можем дойти до ситуации, когда эта абстракция станет независимой частью кода, живущего в нашей кодовой базе. Если мы дойдем до этого момента, возможно, стоит рассмотреть возможность извлечения в надстройку.