Javascript 销毁地图实例的正确方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10485582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:33:21  来源:igfitidea点击:

What is the Proper Way to Destroy a Map Instance?

javascriptgoogle-maps-api-3

提问by Chad Killingsworth

I recently developed an html5 mobile application. The application was a single page where navigation hash change events replaced the entire DOM. One section of the application was a Google Map using API v3. Before the map div is removed from the DOM, I want to remove any event handlers/listeners and free up as much memory as possible as the user may not return to that section again.

我最近开发了一个 html5 移动应用程序。该应用程序是一个页面,其中导航哈希更改事件替换了整个 DOM。该应用程序的一个部分是使用 API v3 的 Google 地图。在从 DOM 中删除地图 div 之前,我想删除任何事件处理程序/侦听器并释放尽可能多的内存,因为用户可能不会再次返回该部分。

What is the best way to destroy a map instance?

销毁地图实例的最佳方法是什么?

采纳答案by Chad Killingsworth

The official answeris you don't. Map instances in a single page application should be reused and not destroyed then recreated.

官方的回答是你不知道。单页应用程序中的地图实例应该被重用,而不是被销毁然后重新创建。

For some single page applications, this may mean re-architecting the solution such that once a map is created it may be hidden or disconnected from the DOM, but it is never destroyed/recreated.

对于某些单页应用程序,这可能意味着重新构建解决方案,这样一旦创建了地图,它就可以隐藏或与 DOM 断开连接,但它永远不会被销毁/重新创建。

回答by Sean Mickey

I'm adding a second answer on this question, because I don't want to remove the back and forth we had via follow-up comments on my previous answer.

我在这个问题上添加了第二个答案,因为我不想删除我们通过对我之前的答案的后续评论进行的来回。

But I recently came across some information that directly addresses your question and so I wanted to share. I don't know if you are aware of this, but during the Google Maps API Office Hours May 9 2012 Video, Chris Broadfoot and Luke Mahe from Google discussed this very questionfrom stackoverflow. If you set the video playback to 12:50, that is the section where they discuss your question.

但我最近遇到了一些直接解决您的问题的信息,所以我想分享一下。我不知道您是否意识到这一点,但在2012 年 5 月 9 日Google Maps API 办公时间视频中,来自 Google 的 Chris Broadfoot 和 Luke Mahe 讨论了来自 stackoverflow 的这个问题。如果您将视频播放时间设置为 12:50,那么这就是他们讨论您的问题的部分。

Essentially, they admit that it is a bug, but also add that they don't really support use cases that involve creating/destroying successive map instances. They strongly recommend creating a single instance of the map and reusing it in any scenario of this kind. They also talk about setting the map to null, and explicitly removing event listeners. You expressed concerns about the event listeners, I thought just setting the map to null would suffice, but it looks like your concerns are valid, because they mention event listeners specifically. They also recommended completely removing the DIV that holds the map as well.

本质上,他们承认这是一个错误,但还补充说他们并不真正支持涉及创建/销毁连续地图实例的用例。他们强烈建议创建地图的单个实例并在任何此类场景中重复使用它。他们还谈到将地图设置为 null,并明确删除事件侦听器。您表达了对事件侦听器的担忧,我认为只需将地图设置为 null 就足够了,但看起来您的担忧是有效的,因为它们特别提到了事件侦听器。他们还建议完全删除保存地图的 DIV。

At any rate, just wanted to pass this along and make sure it is included in the stackoverflow discussion and hope it helps you and others-

无论如何,只是想传递它并确保它包含在stackoverflow讨论中,并希望它可以帮助您和其他人 -

回答by Paolo Mioni

Since apparently you cannot really destroy map instances, a way to reduce this problem if

由于显然您无法真正销毁地图实例,因此如果

  • you need to show several maps at once on a website
  • the number of maps may change with user interaction
  • the maps need to be hidden and re-shown together with other components (ie they do not appear in a fixed position in the DOM)
  • 你需要在一个网站上一次显示多张地图
  • 地图的数量可能会随着用户交互而变化
  • 地图需要与其他组件一起隐藏和重新显示(即它们不会出现在 DOM 中的固定位置)

is keeping a pool of map instances. The pool keeps tracks of instances being used, and when it is requested a new instance, it checks if any of the available map instances is free: if it is, it will return an existing one, if it is not, it will create a new map instance and return it, adding it to the pool. This way you will only have a maximum number of instances equal to the maximum number of maps you ever show simultaneously on screen. I'm using this code (it requires jQuery):

正在保留一个地图实例池。池会跟踪正在使用的实例,当它请求一个新实例时,它会检查是否有任何可用的地图实例是空闲的:如果是,它将返回一个现有的实例,如果不是,它将创建一个新地图实例并返回它,将其添加到池中。这样,您的最大实例数将等于您在屏幕上同时显示的最大地图数。我正在使用此代码(它需要 jQuery):

var mapInstancesPool = {
 pool: [],
 used: 0,
 getInstance: function(options){
    if(mapInstancesPool.used >= mapInstancesPool.pool.length){
        mapInstancesPool.used++;
        mapInstancesPool.pool.push (mapInstancesPool.createNewInstance(options));
    } else { 
        mapInstancesPool.used++;
    }
    return mapInstancesPool.pool[mapInstancesPool.used-1];
 },
 reset: function(){
    mapInstancesPool.used = 0;
 },
 createNewInstance: function(options){
    var div = $("<div></div>").addClass("myDivClassHereForStyling");
    var map =   new google.maps.Map(div[0], options);
    return {
        map: map,
        div: div
    }
 }
}

You pass it the starting map options (as per the second argument of google.maps.Map's constructor), and it returns both the map instance (on which you can call functions pertaining to google.maps.Map), and the container , which you can style using the class "myDivClassHereForStyling", and you can dinamically append to the DOM. If you need to reset the system, you can use mapInstancesPool.reset(). It will reset the counter to 0, while keeping all existing instances in the pool for reuse. In my application I needed to remove all maps at once and create a new set of maps, so there's no function to recycle a specific map instance: your mileage may vary. To remove the maps from the screen, I use jQuery's detach, which doesn't destroy the map's container .

您将起始地图选项传递给它(根据 google.maps.Map 构造函数的第二个参数),它返回地图实例(您可以在其上调用与 google.maps.Map 相关的函数)和容器,其中您可以使用“myDivClassHereForStyling”类来设置样式,并且可以动态地附加到 DOM。如果需要重置系统,可以使用mapInstancesPool.reset()。它将计数器重置为 0,同时保留池中的所有现有实例以供重用。在我的应用程序中,我需要一次删除所有地图并创建一组新地图,因此没有回收特定地图实例的功能:您的里程可能会有所不同。为了从屏幕上移除地图,我使用了 jQuery 的 detach,它不会破坏地图的容器。

By using this system, and using

通过使用这个系统,并使用

google.maps.event.clearInstanceListeners(window);
google.maps.event.clearInstanceListeners(document);

and running

和跑步

google.maps.event.clearInstanceListeners(divReference[0]);
divReference.detach()

(where divReference is the div's jQuery object returned from the Instance Pool) on every div I'm removing, I managed to keep Chrome's memory usage more or less stable, as opposed to it increasing every time I delete maps and add new ones.

(其中 divReference 是从实例池返回的 div 的 jQuery 对象)在我删除的每个 div 上,我设法使 Chrome 的内存使用或多或少保持稳定,而不是每次删除地图和添加新地图时都会增加。

回答by Andrew Leach

I would have suggested removing the content of the map div and using deleteon the variable holding the reference to the map, and probably explicitly deleteing any event listeners.

我会建议删除地图 div 的内容并delete在保存对地图的引用的变量上使用,并且可能明确地delete调用任何事件侦听器。

There is an acknowledged bug, though, and this may not work.

但是,有一个公认的错误,这可能不起作用。

回答by kumar

As google doesnt provide gunload() for api v3 better use iframe in html and assign map.html as a source to this iframe. after use make src as null. That will definitely free the memory consumed by map.

由于谷歌没有为 api v3 提供 gunload() 更好地在 html 中使用 iframe 并将 map.html 作为源分配给这个 iframe。使用后使 src 为空。那肯定会释放地图消耗的内存。

回答by Sean Mickey

When you remove the div, that removes the display panel and the map will disappear. To remove the map instance, just make sure that your reference to the map is set to nulland that any references to other parts of the map are set to null. At that point, JavaScript garbage collection will take care of cleaning up, as described in: How does garbage collection work in JavaScript?.

当您移除 时div,将移除显示面板并且地图将消失。要移除地图实例,只需确保您对地图的引用设置为 ,null并且对地图其他部分的任何引用都设置为null。届时,JavaScript 垃圾收集将负责清理,如:JavaScript 中的垃圾收集如何工作?.

回答by Florian Margaine

I guess you're talking about addEventListener. When you remove the DOM elements, some browsers leak these events and doesn't remove them. This is why jQuery does several things when removing an element:

我猜你在说addEventListener. 当您移除 DOM 元素时,一些浏览器会泄漏这些事件并且不会移除它们。这就是 jQuery 在删除元素时做了几件事的原因:

  • It removes the events when it can using removeEventListener. That means it's keeping an array with the event listeners it added on this element.
  • It deletes the attributes about events (onclick, onblur, etc) using deleteon the DOM element when addEventListeneris not available (still, it has an array where it stores the events added).
  • It sets the element to nullto avoid IE 6/7/8 memory leaks.
  • It then removes the element.
  • 它会在可以使用时删除事件removeEventListener。这意味着它保留了一个数组,其中包含它在此元素上添加的事件侦听器。
  • 当不可用时onclick,它会删除DOM 元素上onblur使用的有关事件(、等)的属性(仍然有一个数组,用于存储添加的事件)。deleteaddEventListener
  • 它将元素设置为null以避免 IE 6/7/8 内存泄漏。
  • 然后它删除元素。