Работа с картографическими библиотеками

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

Подключение библиотеки карты

Для большинства популярных библиотек, таких как Leaflet или Mapbox, требуется подключение CSS и JS файлов через <script> и <link> в HTML-шаблоне либо через npm. В Riot-компоненте подключение обычно выполняется в блоке onMounted, чтобы гарантировать, что DOM готов к инициализации карты.

import { onMounted, onUnmounted } from 'riot';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

export default {
  onMounted() {
    this.map = L.map(this.root.querySelector('.map-container')).setView([55.751244, 37.618423], 10);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; OpenStreetMap contributors'
    }).addTo(this.map);
  },
  onUnmounted() {
    if (this.map) this.map.remove();
  }
}

Ключевые моменты:

  • onMounted обеспечивает корректную инициализацию после рендера DOM.
  • onUnmounted нужен для очистки ресурсов и предотвращения утечек памяти.
  • Использование this.root.querySelector позволяет работать с элементом карты внутри компонента.

Управление маркерами и слоями

Riot.js поддерживает реактивные свойства, что позволяет автоматически обновлять маркеры и слои при изменении данных. Внутри компонента можно создать реактивный массив markers и следить за его изменениями:

this.markers = [];

this.addMarker = (lat, lng, popupText) => {
  const marker = L.marker([lat, lng]).addTo(this.map);
  if (popupText) marker.bindPopup(popupText);
  this.markers.push(marker);
}

this.clearMarkers = () => {
  this.markers.forEach(marker => marker.remove());
  this.markers = [];
}

Особенности работы с Riot.js:

  • Массивы и объекты можно сделать реактивными с помощью this.update().
  • Любое изменение массива маркеров должно сопровождаться вызовом update(), если нужно синхронизировать отображение данных в компоненте.

Динамическое обновление карты

При получении данных с сервера или взаимодействии с пользователем важно обновлять карту без полной перерисовки компонента. Riot.js позволяет манипулировать картой напрямую через методы библиотек. Пример динамического центрирования карты и изменения зума:

this.setView = (lat, lng, zoom = 12) => {
  if (this.map) {
    this.map.setView([lat, lng], zoom);
  }
}

Реактивность Riot.js в данном случае используется не для перерисовки DOM, а для управления состоянием компонентов и передачи новых координат.

Взаимодействие с внешними событиями

Карты часто требуют обработки кликов, перемещений и других событий. Riot.js позволяет добавлять слушатели в onMounted и удалять их в onUnmounted:

this.onMapCl ick = (e) => {
  console.log('Клик по карте', e.latlng);
}

onMounted(() => {
  this.map.on('click', this.onMapClick);
});

onUnmounted(() => {
  this.map.off('click', this.onMapClick);
});

Важно:

  • Удаление обработчиков предотвращает утечки памяти.
  • События карты можно связывать с реактивными данными компонента, чтобы при изменении состояния обновлялись маркеры или слои.

Работа с внешними библиотеками и Riot.js

Riot.js не ограничивает использование сторонних библиотек, но важно соблюдать жизненный цикл компонентов. Любая библиотека, манипулирующая DOM, должна инициализироваться в onMounted. Для реактивного взаимодействия с данными рекомендуется:

  • Использовать this.update() после изменения реактивных свойств.
  • Хранить ссылки на объекты карт и слоев в свойствах компонента (this.map, this.markers).
  • Удалять все внешние ресурсы и слушатели в onUnmounted.

Пример комплексного компонента карты

import { onMounted, onUnmounted } from 'riot';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

export default {
  markers: [],
  
  onMounted() {
    this.map = L.map(this.root.querySelector('.map-container')).setView([55.751244, 37.618423], 10);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);

    this.map.on('click', (e) => {
      this.addMarker(e.latlng.lat, e.latlng.lng, `Координаты: ${e.latlng.lat}, ${e.latlng.lng}`);
    });
  },

  onUnmounted() {
    if (this.map) this.map.remove();
  },

  addMarker(lat, lng, popupText) {
    const marker = L.marker([lat, lng]).addTo(this.map);
    if (popupText) marker.bindPopup(popupText);
    this.markers.push(marker);
    this.update();
  },

  clearMarkers() {
    this.markers.forEach(marker => marker.remove());
    this.markers = [];
    this.update();
  }
}

Такой подход обеспечивает гибкое управление картой, реактивные обновления маркеров и безопасное освобождение ресурсов, полностью используя возможности Riot.js и сторонних картографических библиотек.