5

我经历了尽可能多的 StackOverflow/google 小组,我可以想象试图找出这个人。

我正在使用 BackboneJS 呈现具有起始位置和结束位置的地图。在新的页面/页面刷新时,我没有收到此错误,并且地图和东西工作正常,因为我使用的是 jQuery 的 $(window).load(.....) 函数;然而,当我动态渲染我的视图时,我得到了这个错误——我相信——因为 DOM 还没有加载 DIV(由于 document.getElementById 失败)。除了 $(window).load() 之外,我已经尝试了各种不同的方法,但我无法获得适用于这两种用例的任何方法(新页面加载——BackboneJS 视图加载)。尝试在模板之后立即调用该函数也不起作用。

任何帮助,将不胜感激。

罗伯特

看法:

    App.Views.MapShow = Backbone.View.extend({
      initialize: function() {
        _.bindAll(this, 'render');
        var self = this;
        $(window).load(function() {
          self.renderMap();
        });
      },

      render: function() {
        this.renderTemplate();
      },

      renderTemplate: function() {
        this.$el.html(JST['path/to/show/file']());
      },

      renderMap: function() {
        var from     = this.model.get('location_from');
        var to       = this.model.get('location_to');
        var geocoder = new google.maps.Geocoder();
        var map      = new google.maps.Map(document.getElementById('mapCanvas'), {
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });
        var directionsService = new google.maps.DirectionsService();
        var directionsDisplay = new google.maps.DirectionsRenderer();

        directionsDisplay.setMap(map);

        var request = {
          origin: from,
          destination: to,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };

        directionsService.route(request, function(response, status) {
          if (status == google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
          }
        });
      }
    });

HTML:

    <div class="map" id="mapCanvas"></div>
4

1 回答 1

7

我猜你的问题是#mapCanvas在你尝试访问它之前它不在 DOM 中,所以这样:

document.getElementById('mapCanvas')

会给你一个没用的null。您需要等到#mapCanvas它在 DOM 中才能使用它;你也不能这样做:

map_canvas = this.$el.find('#mapCanvas')[0];

这会给你一个有效的 ID,但你会混淆谷歌地图的功能,因为它没有大小,所以地图会奇怪地呈现。这让您在绑定 Google 地图内容之前重新等待所有内容都在 DOM 中。

解决此问题的一种方法是使用setTimeout延迟为零

var _this = this;
setTimeout(function() { _this.renderMap() }, 0);

这看起来有点奇怪,它确实有效,这个技巧基本上将你的renderMap调用转储到浏览器的工作队列中,一旦你将控制权返回给浏览器,它就会开始运行它。

您还可以使用_.defer

推迟 _.defer(function, [*arguments])

延迟调用函数,直到当前调用堆栈被清除,类似于使用延迟为 0 的setTimeout。对于在不阻塞 UI 线程更新的情况下以块执行昂贵的计算或 HTML 呈现很有用。

这可能是一个更好的选择,因为它使您的意图明确。

于 2012-08-12T23:05:18.607 回答