DOM 完全加载后,我如何获得到 运行 函数的 turbolinks?

How do I get turbolinks to run a function once the DOM is completely loaded?

document.addEventListener('turbolinks:load', () => {}); 未按预期工作。 Mapbox 抛出以下错误:Uncaught Error: Container 'map' not found. 并且地图只有在我重新加载页面后才能正确显示。

下面是一些有助于更好理解的代码。

Javascript 用于 mapbox 导入和设置:

// app/javascript/plugins/init_mapbox.js

import mapboxgl from 'mapbox-gl';

const mapElement = document.getElementById('map');

const buildMap = () => {
  mapboxgl.accessToken = mapElement.dataset.mapboxApiKey;
  return new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v10'
  });
};

const addMarkersToMap = (map, markers) => {
  markers.forEach((marker) => {
    new mapboxgl.Marker()
      .setLngLat([ marker.lng, marker.lat ])
      .addTo(map);
  });
};

const fitMapToMarkers = (map, markers) => {
  const bounds = new mapboxgl.LngLatBounds();
  markers.forEach(marker => bounds.extend([ marker.lng, marker.lat ]));
  map.fitBounds(bounds, { padding: 70, maxZoom: 15 });
};

const initMapbox = () => {
  if (mapElement) {
    const map = buildMap();
    const markers = JSON.parse(mapElement.dataset.markers);
    console.log(markers)
    addMarkersToMap(map, markers);
    fitMapToMarkers(map, markers);
  }
};

export { initMapbox };

在 application.js 中导入:

// app/javascript/packs/application.js

import { initMapbox } from '../plugins/init_mapbox';

[...]

document.addEventListener('turbolinks:load', () => {
  initMapbox();
});

HTML:

<!-- app/views/spaces/index.html.erb -->

[...]

<div id="map"
     style="width: 100%; height: 600px;"
     data-markers="<%= @markers.to_json %>"
     data-mapbox-api-key="<%= ENV['MAPBOX_API_KEY'] %>">
</div>

[...]

我完全迷失在这一点上。有任何想法吗?有人让这个工作吗?

问题是您在导入文件时分配 mapElement。不是在 DOM 准备就绪或 turbolinks 执行页面访问时。

如果您只是重写此代码,以便您的函数将一个元素作为参数,而不是依赖外部作用域中的变量,那么解决它就很简单了:

import mapboxgl from 'mapbox-gl';

const buildMap = (mapElement) => {
  mapboxgl.accessToken = mapElement.dataset.mapboxApiKey;
  return new mapboxgl.Map({
    container: mapElement,
    style: 'mapbox://styles/mapbox/streets-v10'
  });
};

const addMarkersToMap = (map, markers) => {
  markers.forEach((marker) => {
    new mapboxgl.Marker()
      .setLngLat([ marker.lng, marker.lat ])
      .addTo(map);
  });
};

const fitMapToMarkers = (map, markers) => {
  const bounds = new mapboxgl.LngLatBounds();
  markers.forEach(marker => bounds.extend([ marker.lng, marker.lat ]));
  map.fitBounds(bounds, { padding: 70, maxZoom: 15 });
};

const initMapbox = (mapElement) => {
  const map = buildMap(mapElement);
  const markers = JSON.parse(mapElement.dataset.markers);
  console.log(markers)
  addMarkersToMap(map, markers);
  fitMapToMarkers(map, markers);
};

然后您在回调函数中查询 DOM:

document.addEventListener('turbolinks:load', () => {
  const mapElement = document.getElementById('map');
  if (mapElement) {
    initMapbox(mapElement);
  }
});

此外,我不知道这是否是复制粘贴问题,但您的 HTML 也缺少 <div id="map"> 中的括号。