javascript удалить - Каков правильный способ уничтожить экземпляр карты?




свойство объекта (7)

Недавно я разработал мобильное приложение html5. Приложение представляло собой единую страницу, в которой события изменения хэша навигации заменяли всю DOM. Одним из разделов приложения была карта Google, использующая API v3. Перед удалением карты div из DOM я хочу удалить любые обработчики / прослушиватели событий и освободить как можно больше памяти, поскольку пользователь не может снова вернуться к этому разделу.

Каков наилучший способ уничтожить экземпляр карты?


Answers

Официальный ответ - нет. Экземпляры карт в одностраничном приложении должны быть повторно использованы и не уничтожены, а затем воссозданы.

Для некоторых приложений с одной страницей это может означать повторное архивирование решения таким образом, что после создания карты он может быть скрыт или отключен от DOM, но он никогда не уничтожается / не воссоздается.


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

  • вам нужно показать сразу несколько карт на веб-сайте
  • количество карт может меняться при взаимодействии с пользователем
  • карты должны быть скрыты и повторно показаны вместе с другими компонентами (т.е. они не отображаются в фиксированной позиции в DOM)

хранит пул экземпляров карты. Пул хранит следы используемых экземпляров, и когда запрашивается новый экземпляр, он проверяет, свободен ли какой-либо из доступных экземпляров карты: если он есть, он вернет существующий, если это не так, он создаст новый экземпляр карты и верните его, добавив его в пул. Таким образом, у вас будет только максимальное количество экземпляров, равное максимальному количеству карт, которые вы когда-либо показывали на экране. Я использую этот код (для этого требуется 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
    }
 }
}

Вы передаете ему исходные параметры карты (в соответствии со вторым аргументом конструктора google.maps.Map), и он возвращает оба экземпляра карты (на которые вы можете вызывать функции, относящиеся к google.maps.Map), и контейнер, который вы можете использовать стиль «myDivClassHereForStyling», и вы можете динамически добавить в DOM. Если вам нужно сбросить систему, вы можете использовать mapInstancesPool.reset (). Он сбрасывает счетчик на 0, сохраняя все существующие экземпляры в пуле для повторного использования. В моем приложении мне нужно было сразу удалить все карты и создать новый набор карт, поэтому нет возможности перерабатывать конкретный экземпляр карты: ваш пробег может отличаться. Чтобы удалить карты с экрана, я использую отсоединение jQuery, которое не уничтожает контейнер карты.

Используя эту систему и используя

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

и работает

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

(где divReference - это объект jQuery div, возвращаемый из пула экземпляров) на каждом div, который я удаляю, мне удалось сохранить использование памяти Chrome более или менее стабильным, а не увеличивать каждый раз, когда я удаляю карты и добавляю новые.


Думаю, вы говорите о addEventListener . Когда вы удаляете элементы DOM, некоторые браузеры пропускают эти события и не удаляют их. Вот почему jQuery выполняет несколько операций при удалении элемента:

  • Он удаляет события, когда он может использовать removeEventListener . Это означает, что он хранит массив с слушателями событий, которые он добавил в этот элемент.
  • Он удаляет атрибуты событий ( onclick , onblur и т. Д.), Используя delete в элементе DOM, когда addEventListener недоступен (но у него есть массив, в котором он хранит добавленные события).
  • Он устанавливает для элемента значение null чтобы избежать утечек памяти IE 6/7/8.
  • Затем он удаляет элемент.

Когда вы удаляете div , это удаляет панель дисплея, и карта исчезнет. Чтобы удалить экземпляр карты, просто убедитесь, что ваша ссылка на карту установлена ​​в null и что любые ссылки на другие части карты имеют значение null . В этот момент сборка мусора JavaScript позаботится об очистке, как описано в: Как сборка мусора работает в JavaScript? ,


Поскольку google не предоставляет gunload () для api v3, лучше использовать iframe в html и назначать map.html в качестве источника для этого iframe. после использования сделайте src равным нулю. Это определенно освободит память, потребляемую картой.


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

Однако есть признанная ошибка , и это может не сработать.


Глубокая копия по производительности: от лучших до худших

  • Переназначение «=» (строковые массивы, числовые массивы - только)
  • Slice (строковые массивы, массивы чисел - только)
  • Конкатенация (только массивы строк, числовые массивы)
  • Пользовательская функция: for-loop или рекурсивная копия
  • jQuery's $ .extend
  • JSON.parse (только строковые массивы, массивы чисел, массивы объектов)
  • Underscore.js _.clone (только массивы строк, числовые массивы - только)
  • Lo-Dash's _.cloneDeep

Глубоко скопируйте массив строк или чисел (один уровень - без указателей):

Когда массив содержит числа и строки - такие функции, как .slice (), .concat (), .splice (), оператор присваивания «=» и функция клона Underscore.js; сделает глубокую копию элементов массива.

Если переназначение имеет самую высокую производительность:

var arr1 = ['a', 'b', 'c'];
var arr2 = arr1;
arr1 = ['a', 'b', 'c'];

И .slice () имеет лучшую производительность, чем .concat (), http://jsperf.com/duplicate-array-slice-vs-concat/3

var arr1 = ['a', 'b', 'c'];  // Becomes arr1 = ['a', 'b', 'c']
var arr2a = arr1.slice(0);   // Becomes arr2a = ['a', 'b', 'c'] - deep copy
var arr2b = arr1.concat();   // Becomes arr2b = ['a', 'b', 'c'] - deep copy

Глубоко скопируйте массив объектов (два или более уровней - указатели):

var arr1 = [{object:'a'}, {object:'b'}];

Напишите пользовательскую функцию (имеет более высокую производительность, чем $ .extend () или JSON.parse):

function copy(o) {
   var out, v, key;
   out = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       out[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
   }
   return out;
}

copy(arr1);

Используйте сторонние служебные функции:

$.extend(true, [], arr1); // Jquery Extend
JSON.parse(arr1);
_.cloneDeep(arr1); // Lo-dash

Где $ .extend jQuery имеет лучшую производительность:







javascript google-maps-api-3