Leaflet: peta tidak dihapus sepenuhnya di map.remove() dari DOM

Dibuat pada 13 Sep 2017  ·  37Komentar  ·  Sumber: Leaflet/Leaflet

Cara memperbanyak

  • Versi selebaran yang saya gunakan: 1.2.0
  • Browser (dengan versi) Saya menggunakan: Chrome Versi 60.0.3112.113
  • Ini berfungsi dengan baik di Firefox dan Safari (belum diuji di IE, Edge)
  • OS/Platform (dengan versi) Saya menggunakan: macOS Sierra
  • tambahkan peta di elemen div dan tambahkan layer
this.leafletMap = new L.Map( <element> , {
            zoomControl: true, 
            dragging: this.isInDragMode, 
            touchZoom: false,
            scrollWheelZoom: false,
            doubleClickZoom: false,
            tap: false,
}
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                } ).addTo( this.leafletMap );
  • Hapus peta pada beberapa tindakan pengguna
if (this.leafletMap ){
        this.leafletMap.eachLayer(function(layer){
            layer.remove();
        });
        this.leafletMap.remove();
        this.leafletMap = null;
    }

Perilaku apa yang saya harapkan dan perilaku apa yang saya lihat

  • Pasca penghapusan peta, itu menghapus peta dari elemen, namun, jika saya mengklik dua kali pada div, itu menimbulkan kesalahan - Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined
    Sepertinya elemen DOM masih menahan pendengar acara meskipun peta dan lapisannya dihapus.

Contoh minimal mereproduksi masalah

  • [ ] contoh ini sesederhana mungkin
  • [ ] contoh ini tidak bergantung pada kode pihak ketiga mana pun

Menggunakan http://playground-leaflet.rhcloud.com/ atau situs serupa jsfiddle lainnya.

needs more info

Komentar yang paling membantu

@spydmobile begini, inilah yang saya lakukan dalam bentuk yang sedikit dimodifikasi:
Saya tidak tahu cara memposting kode dengan benar di bidang komentar f * ing ini, maaf tentang itu.
Saya telah mengedit komentar saya sendiri sekitar 10 kali sekarang lol

function removeMap()
{
    var leafletCtrl = get_your_own_leaflet_reference_from_somewhere(), 
    dom = leafletCtrl.getReferenceToContainerDomSomehow(); 

    //This removes most of the events
    leafletCtrl.off();

//After this, the dom element should be good to reuse, unfortunatly it is not
    leafletCtrl.remove(); 

    var removeDanglingEvents = function(inputObj, checkPrefix)
    {
        if(inputObj !== null)
        {
            //Taken from the leaflet sourcecode directly, you can search for these constants and see how those events are attached, why they are never fully removed i don't know
            var msPointer = L.Browser.msPointer,
            POINTER_DOWN =   msPointer ? 'MSPointerDown'   : 'pointerdown',
            POINTER_MOVE =   msPointer ? 'MSPointerMove'   : 'pointermove',
            POINTER_UP =     msPointer ? 'MSPointerUp'     : 'pointerup',
            POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';

            for(var prop in inputObj)
            {
                var prefixOk = checkPrefix ? prop.indexOf('_leaflet_') !== -1 : true, propVal; //if we are in the _leaflet_events state kill everything, else only stuff that contains the string '_leaflet_'
                if(inputObj.hasOwnProperty(prop) && prefixOk)
                {
                    //Map the names of the props to the events that were really attached => touchstart equals POINTER_DOWN etc
                    var evt = []; 
                    if(prop.indexOf('touchstart') !== -1) //indexOf because the prop names are really weird 'touchstarttouchstart36' etc
                    {
                        evt = [POINTER_DOWN];
                    }
                    else if(prop.indexOf('touchmove') !== -1)
                    {
                        evt = [POINTER_MOVE];
                    }
                    else if(prop.indexOf('touchend') !== -1)
                    {
                        evt = [POINTER_UP, POINTER_CANCEL];
                    }

                    propVal = inputObj[prop];
                    if(evt.length > 0 && typeof propVal === 'function')
                    {
                        evt.each(function(domEvent)
                        {
                            dom.removeEventListener(domEvent, propVal, false);
                        });                    
                    }

                    //Reference B-GONE, Garbage b collected.
                    inputObj[prop] = null;
                    delete inputObj[prop];
                }
            }
        }        
    };

    removeDanglingEvents(dom._leaflet_events, false);
    removeDanglingEvents(dom, true);
}

Semua 37 komentar

Hai dan terima kasih telah meluangkan waktu untuk melaporkan bug ini.

Namun, tampaknya ada sesuatu yang hilang dari langkah-langkah yang Anda jelaskan untuk mereproduksi masalah. Saya menyiapkan contoh taman bermain sebaik mungkin di sepanjang langkah-langkah di atas: http://playground-leaflet.rhcloud.com/rezop/edit?html ,output

Dalam contoh ini, saya tidak dapat melihat kesalahan apa pun setelah peta dihapus, jadi tampaknya ada hal lain yang menyebabkan masalah yang Anda lihat. Bisakah Anda memberikan detail lebih lanjut, sehingga kami dapat melacaknya.

@perliedman Terima kasih atas respons cepat dan menyusun contoh taman bermain. Saya tidak dapat mereproduksi yang satu itu. Mencoba beberapa skenario lagi. sementara saya masih menyelidikinya, beberapa pertanyaan -

Apakah saya perlu menghapus Layer secara eksplisit, jika saya melakukan map.remove() ? tebakan saya adalah, itu akan menangani penghapusan lapisan juga, tetapi dapatkah Anda mengonfirmasi.

Dan alasan Anda memiliki map.remove() di bawah batas waktu adalah bahwa dalam contoh Anda menghancurkan peta tepat setelah pembuatan, jika tidak maka tidak perlu ditutup dengan batas waktu. benar?

Ingat, saat bekerja dengan open source, _use_ the source! :wink: Untuk menjawab pertanyaan pertama Anda, _yes_, remove akan menghapus lapisan: https://github.com/Leaflet/Leaflet/blob/master/src/map/Map.js#L731

Alasan saya memasukkannya ke dalam batas waktu adalah untuk membuat contoh saya sedikit lebih realistis, memastikan lapisan ubin benar-benar diinisialisasi dengan benar dengan ubin yang dimuat, dll. Contoh berfungsi dengan baik tanpa memasukkan panggilan remove batas waktu, tapi sepertinya ini semacam tes buatan.

Halo - Saya pikir saya juga mengalami masalah ini. Inilah kasus penggunaan dasar saya:

Saya sedang membangun komponen penampil (menggunakan plugin Leaflet-IIIF , tapi saya rasa itu tidak memengaruhi apa pun di sini) untuk objek dengan banyak halaman/permukaan yang bertentangan dengan menampilkan peta yang sebenarnya. Saat penampil dimuat, ada serangkaian gambar mini yang dapat diklik pengguna untuk memperbarui tampilan objek mana yang ditampilkan di area tengah UI.

Saat pengguna mengubah tampilan, saya memanggil map.remove() sebelum menyiapkan peta baru untuk tampilan baru. Peta baru dibuat pada elemen DOM yang sama dengan yang lama (div dengan ID), dan saya tidak memodifikasi DOM dengan cara apa pun di luar Leaflet.

Pada tampilan awal semuanya berfungsi dengan baik. Tetapi setelah memanggil map.remove() dan menampilkan tampilan baru, konsol mengeluh: Cannot read property '_leaflet_pos' of undefined setiap kali peta diseret atau diperbesar.

Saya dapat mencoba memposting contoh minimal di beberapa titik, tetapi ini tampaknya menjadi masalah yang sama. Kesalahan ini muncul di Chrome tetapi tidak di Firefox.

@egardner ya, coba buat contoh yang mereproduksi ini!

@egardner masalah yang sama persis pada aplikasi elektron (Chromium + Node) yang sebelumnya stabil yang harus saya kembalikan ke:
"leaflet": "1.0.0",
"leaflet.markercluster": "1.0.0-rc.1.0"
dari 1.2.0 untuk menghapus kesalahan Tidak dapat membaca properti '_leaflet_pos' dari undefined
Ini juga setelah map.remove() sebelum membuat ulang peta di elemen DOM yang sama. Saya tidak punya waktu sekarang untuk membuat dan memberi contoh dalam jangka pendek

Kami juga mengalami masalah serupa saat mencoba menghancurkan peta, tampaknya berpegang pada referensi

Saya akan mengulangi apa yang saya katakan di atas: agar kami dapat melakukan apa pun tentang masalah ini, berikan contoh yang mereproduksi masalah.

Hai. Saya telah mereproduksi kesalahan ini dalam biola. Sederhananya, jika Anda membuat peta di dalam elemen div, lalu gunakan metode hapus, lalu isi kembali peta di div yang sama, setiap pemindahan peta akan menghasilkan kesalahan
TypeError Tidak Tertangkap: Tidak dapat membaca properti '_leaflet_pos' dari undefined.

Untuk mereproduksi, buka biola saya, klik hapus peta, klik peta tempat, lalu buka konsol dan pindahkan peta.
http://jsfiddle.net/spydmobile/5hmadjnk/

Catatan, itu hanya terjadi di Chorme, bukan di FF

Ya spydmobile terima kasih untuk contohnya, ini adalah kesalahan yang sama yang saya lihat di Chrome seperti yang saya laporkan di atas

Saya melihat kesalahan yang sama tetapi dalam kasus penggunaan yang sedikit berbeda. Kesalahan yang sama terjadi pada pengubahan ukuran karena panggilan invalidateSize :

Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined
    at getPosition (leaflet-src.js:2765)
    at NewClass._getMapPanePos (leaflet-src.js:4378)
    at NewClass._rawPanBy (leaflet-src.js:4180)
    at NewClass.invalidateSize (leaflet-src.js:3509)
    at NewClass.<anonymous> (leaflet-src.js:4244)

Tumpukan panggilan penuh dimulai pada handler _onResize . Saya menggunakan react-leaflet tetapi tidak ada bagian dari jejak tumpukan yang mengarah ke sana atau kode lokal menjadi masalahnya. Saya memang mencoba beberapa versi yang lebih lama (misalnya 1.0.3 dan 1.2.0 ) berpikir kami mungkin setidaknya dapat menguncinya ke versi 1.x.x , tetapi tidak berhasil.

Apakah ada pembaruan tentang ini? Memiliki Masalah yang sama di sini mengintegrasikan selebaran ke dalam aplikasi saya. Setelah peta dihancurkan, elemen dom masih memiliki properti _leaflet_events, tetapi menyingkirkan objek ini juga tidak membantu.

Tampaknya konteks fungsi handler sudah basi (properti pribadi _mapPane di args handler menunjuk ke elemen yang tidak ada).

saya juga sedang mengalami ini. Ini adalah salah satu pengecualian yang saya lihat:

https://sentry.io/share/issue/b414c58ea85c44ee9e0e40ad0781883a/

Tampaknya ini sebagian besar terjadi ketika pengguna menggunakan tombol kembali browser untuk meninggalkan peta.

Saya pikir saya mungkin telah menemukan solusinya:

Div wadah Peta masih memiliki beberapa peristiwa yang dipicu bahkan setelah map.off dan map.remove .

Dalam kasus saya, peta memiliki properti yang dimulai dengan _leaflet_ dan beberapa fungsi tersebut saya temukan ada di peta itu sendiri di properti "map._leaflet_events".

Itu tampaknya dilampirkan sebagai pointerdown , pointermove dan semacamnya tetapi nama-nama Properti seperti map._leaflet_touchstarttouchstart32 dll.

Saya menemukan bahwa jika saya mengulanginya dan menghapusnya secara manual (menggunakan removeEventListener lalu membatalkan dan menghapus properti itu sendiri untuk ukuran yang baik), saya dapat menggunakan kembali div untuk peta lain.
Ini juga mengakhiri kebocoran memori yang saya lihat.

Saya tidak dapat memposting kode di sini, tetapi jika Anda mencari sumber selebaran untuk POINTER_DOWN Anda akan melihat acara yang dilampirkan, dan tahu cara melepaskannya.

Saya dapat mereproduksi ini di Chrome tetapi juga di FF (baik di proyek saya sendiri dan dengan jsfiddle yang disediakan oleh @spydmobile)

@FLoibl Mungkin intisari, biola, atau cuplikan yang diposting di tempat lain untuk menunjukkan teknik yang berhasil Anda gunakan untuk mengatasinya?

@spydmobile begini, inilah yang saya lakukan dalam bentuk yang sedikit dimodifikasi:
Saya tidak tahu cara memposting kode dengan benar di bidang komentar f * ing ini, maaf tentang itu.
Saya telah mengedit komentar saya sendiri sekitar 10 kali sekarang lol

function removeMap()
{
    var leafletCtrl = get_your_own_leaflet_reference_from_somewhere(), 
    dom = leafletCtrl.getReferenceToContainerDomSomehow(); 

    //This removes most of the events
    leafletCtrl.off();

//After this, the dom element should be good to reuse, unfortunatly it is not
    leafletCtrl.remove(); 

    var removeDanglingEvents = function(inputObj, checkPrefix)
    {
        if(inputObj !== null)
        {
            //Taken from the leaflet sourcecode directly, you can search for these constants and see how those events are attached, why they are never fully removed i don't know
            var msPointer = L.Browser.msPointer,
            POINTER_DOWN =   msPointer ? 'MSPointerDown'   : 'pointerdown',
            POINTER_MOVE =   msPointer ? 'MSPointerMove'   : 'pointermove',
            POINTER_UP =     msPointer ? 'MSPointerUp'     : 'pointerup',
            POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';

            for(var prop in inputObj)
            {
                var prefixOk = checkPrefix ? prop.indexOf('_leaflet_') !== -1 : true, propVal; //if we are in the _leaflet_events state kill everything, else only stuff that contains the string '_leaflet_'
                if(inputObj.hasOwnProperty(prop) && prefixOk)
                {
                    //Map the names of the props to the events that were really attached => touchstart equals POINTER_DOWN etc
                    var evt = []; 
                    if(prop.indexOf('touchstart') !== -1) //indexOf because the prop names are really weird 'touchstarttouchstart36' etc
                    {
                        evt = [POINTER_DOWN];
                    }
                    else if(prop.indexOf('touchmove') !== -1)
                    {
                        evt = [POINTER_MOVE];
                    }
                    else if(prop.indexOf('touchend') !== -1)
                    {
                        evt = [POINTER_UP, POINTER_CANCEL];
                    }

                    propVal = inputObj[prop];
                    if(evt.length > 0 && typeof propVal === 'function')
                    {
                        evt.each(function(domEvent)
                        {
                            dom.removeEventListener(domEvent, propVal, false);
                        });                    
                    }

                    //Reference B-GONE, Garbage b collected.
                    inputObj[prop] = null;
                    delete inputObj[prop];
                }
            }
        }        
    };

    removeDanglingEvents(dom._leaflet_events, false);
    removeDanglingEvents(dom, true);
}

Ah triple backtick, mengerti, ty.

@FLoibl Ini adalah investigasi yang sangat bagus :+1:

Bisakah Anda menambahkan beberapa logging di sekitar ... ? https://github.com/Leaflet/Leaflet/blob/5161140e952969c5da27751b79154a2c93f53bfa/src/dom/DomEvent.Pointer.js#L39 dan https://github.com/Leaflet/Leaflet/blob/fe9e0f2333888e/8c02b9e37d js#L133

Itu harus berjalan untuk setiap acara ketika L.Map dihancurkan, dan harus melakukan hal yang sama seperti yang Anda lakukan, tetapi saya bertanya-tanya mengapa itu tidak berfungsi seperti yang diharapkan.

Ya, saya tahu fungsi itu dan saya melihatnya dipanggil, tetapi tidak untuk semua acara.

Saya pikir masalahnya adalah bahwa kode melampirkannya sebagai "pointermove" dll ke dom, tetapi nama propertinya adalah "touchstart" dll. Juga kata "touchstart" terlihat dua kali dalam nama properti, mungkin doube concat yang tidak terduga dari id dan nama acara?

Juga haruskah acara "penunjuk" itu dilampirkan di Windows 10 tanpa Layar Sentuh dan di Chrome?
Sayangnya, saya tidak cukup tahu tentang cara kerja selebaran untuk memberikan perbaikan nyata :-(

saya tahu fungsi itu dan saya melihatnya dipanggil, tetapi tidak untuk semua acara.

Sekarang pertanyaannya adalah: Apa acara yang removePointerListener tidak dipanggil? Mungkin kita kehilangan panggilan fungsi di sini atau di sana.

Juga haruskah acara "penunjuk" itu dilampirkan di Windows 10 tanpa Layar Sentuh dan di Chrome?

Ya. Hampir tidak mungkin untuk mendeteksi apakah suatu sistem memiliki layar sentuh, jadi jika browser mendukung peristiwa penunjuk, asumsinya adalah bahwa peristiwa itu akan digunakan.

saya tidak cukup tahu tentang cara kerja selebaran untuk memberikan perbaikan nyata :-(

Hei, jangan putus asa, ini pekerjaan investigasi yang bagus! :senyum:

Bug ini tidak ada di versi 1.0.3. Saya mengambil @spydmobile jsfiddle dan mengubah versi selebaran dan kesalahannya hilang http://jsfiddle.net/5hmadjnk/47/ . Dengan versi 1.1.0 itu sudah ada.

@benru89 Bug ini sebenarnya ada di 1.0.3, dalam bentuk https://github.com/Leaflet/Leaflet/issues/5263 (kebanyakan diperbaiki oleh https://github.com/Leaflet/Leaflet/pull/ 5265).

Perubahan dari 1.0.3 ke 1.1.0 juga memengaruhi L.Mixin.Events dan rollupJS build yang sekarang tidak digunakan lagi, jadi saya rasa ini tidak dapat dilacak dengan baik, bahkan dengan git bisect .

@IvanSanchez saya membandingkan fungsi hapus di 1.0.3 dan 1.1.0 dan ini ditambahkan:

for (i in this._panes) {
    remove(this._panes[i]);
}
this._layers = [];
this._panes = [];
delete this._mapPane;
delete this._renderer;

Jika saya menghapus baris ke-6, baris yang menghapus mapPane kesalahannya hilang. Saya tidak tahu dampak penghapusan ini, saya kira mapPane harus dihapus tetapi bug ini tentu saja diperkenalkan ketika baris itu ditambahkan.

@benru89 Wow, itu juga info yang bagus :+1:

Saya hanya tidak melihat pointer event handler apa yang ada di panel peta sekarang, meskipun :thinking:

Saya pikir dengan tidak menghapus panel peta, Anda hanya menutupi masalahnya. Ketika saya melacak tumpukan panggilan, masalahnya adalah bahwa beberapa Objek _mapPane menunjuk ke elemen dom yang dihancurkan sehingga mencoba untuk mendapatkan posisi yang di-cache dari yang tidak ditentukan. Jika panel tidak dihancurkan, peristiwa hantu mungkin terjadi tanpa memicu pengecualian.

@Floibl Saya setuju dengan Anda, saya pikir itu bukan solusinya, tetapi saya perhatikan _mapPane nol ketika memeriksa tumpukan panggilan jadi itu sebabnya saya mencoba untuk tidak menghapus baris itu. Solusinya harus di sisi menghapus penangan acara dengan benar, saya kira.

Saya pikir event handler yang menyebabkan ini (setidaknya dalam kasus saya dan @spydmobile ) disebut "touchExtend" jadi ini adalah handler leaflet.draw. Saya menemukan bahwa menghapus impor untuk leaflet.draw menghentikan pengecualian juga.

Saya menemukan solusi lain. Menginisialisasi peta Anda dengan opsi tidak berdokumen touchExtend : false menonaktifkan handler yang bermasalah, jadi tidak ada lagi pengecualian. Saya tidak benar-benar tahu fitur apa yang saya hilangkan dengan melakukan itu, tetapi melihat kodenya, itu bisa menjadi beberapa gerakan yang diperluas untuk ponsel atau layar sentuh ?? Bagaimanapun di aplikasi saya semuanya tampak berfungsi dengan baik.

@IvanSanchez Saya tidak yakin ini masalah yang sama, tetapi bisa jadi terkait.
Saat Anda menghancurkan peta saat animasi zoom sedang berlangsung, Anda mendapatkan kesalahan yang sama: Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined .

Saya mencoba melihat ke dalam kode dan menemukan bahwa di dalam Map._animateZoom() ada baris: setTimeout(Util.bind(this._onZoomTransitionEnd, this), 250);
Jika saya cukup memahaminya, batas waktu ini tidak dihancurkan ketika peta dihapus, jadi fungsi Map._onZoomTransitionEnd selalu dipanggil. Ini bisa jadi _"Anda melewatkan panggilan fungsi di sini atau di sana"_.

Dan pohon panggilan yang disederhanakan this._onZoomTransitionEnd -> this._move -> this._getNewPixelOrigin -> this._getMapPanePos -> getPosition(this._mapPane) -> return el._leaflet_pos gagal, karena this._mapPane adalah _undefined_.

Mungkin kasus ini bisa diperbaiki, jika Anda membungkus panggilan this._move dan this._moveEnd ke dalam kondisi if (this._mapPane) {} , tetapi saya tidak menguji apakah itu memiliki konsekuensi lain.

Ganti ini:

_onZoomTransitionEnd: function () {
    if (!this._animatingZoom) { return; }

    if (this._mapPane) {
        removeClass(this._mapPane, 'leaflet-zoom-anim');
    }

    this._animatingZoom = false;

    this._move(this._animateToCenter, this._animateToZoom);

    // This anim frame should prevent an obscure iOS webkit tile loading race condition.
    requestAnimFrame(function () {
        this._moveEnd(true);
    }, this);
}

dengan ini:

_onZoomTransitionEnd: function () {
    if (!this._animatingZoom) { return; }

    this._animatingZoom = false;

    if (this._mapPane) {
        removeClass(this._mapPane, 'leaflet-zoom-anim');
        this._move(this._animateToCenter, this._animateToZoom);

        // This anim frame should prevent an obscure iOS webkit tile loading race condition.
        requestAnimFrame(function () {
            this._moveEnd(true);
        }, this);
    }
}

Ada pembaruan tentang ini? Saya mengalami masalah yang sama. touchExtend : false tidak membantu. Masalah terjadi ketika saya menavigasi menjauh dari tampilan, di mana saya memiliki peta (pada saat ini sedang dihancurkan dengan memanggil map.remove()) dan kemudian saya menavigasi kembali ke tampilan ini. Itu harus membuat dan menginisialisasi peta baru, tetapi saya mendapatkan kesalahan '_leaflet_pos' di getPosition dalam metode setMaxBounds :

Uncaught (in promise) TypeError: Cannot read property '_leaflet_pos' of undefined
    at getPosition (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:2445)
    at NewClass._getMapPanePos (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4409)
    at NewClass._moved (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4413)
    at NewClass.getCenter (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3774)
    at NewClass.panInsideBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3488)
    at NewClass._panInsideMaxBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4220)
    at NewClass.setMaxBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3444)

Dan juga dalam metode setView :

Uncaught (in promise) TypeError: Cannot read property '_leaflet_pos' of undefined at getPosition (leaflet-src.js?9eb7:2445) at NewClass._getMapPanePos (leaflet-src.js?9eb7:4409) at NewClass.containerPointToLayerPoint (leaflet-src.js?9eb7:3989) at NewClass._getCenterLayerPoint (leaflet-src.js?9eb7:4446) at NewClass._getCenterOffset (leaflet-src.js?9eb7:4451) at NewClass._tryAnimatedPan (leaflet-src.js?9eb7:4526) at NewClass.setView (leaflet-src.js?9eb7:3181)

Masalah yang sama setelah map.remove(), pasang kembali peta saya dan dapatkan kesalahan persis ini

Masalah yang sama dengan v1.6.0. Ini adalah masalah yang rumit

Inilah SSCCE: https://jsfiddle.net/0oafw694/1/

Pada dasarnya, menjalankan kode berikut ...

map = L.map('map');
map.setView(...);
map.setMaxBounds(...);
map.remove();

… meninggalkan dua pendengar acara terlampir:

moveend: (1) […]
0: Object { fn: _panInsideMaxBounds(), ctx: undefined } // from setMaxBounds

unload: (2) […]
0: Object { fn: _destroy() , ctx: {…} }
1: Object { fn: _destroyAnimProxy(), ctx: undefined }

zoomanim: (1) […]
0: Object { fn: _createAnimProxy(), ctx: undefined }

Saya kira, zoomanim/_createAnimProxy ditangani melalui unload/_destroyAnimProxy , dan dengan demikian tidak ada masalah. Tetapi moveend/_panInsideMaxBounds perlu dibatalkan pendaftarannya. Saya akan menyiapkan PR…

Saya baru saja membuat div untuk peta yang memiliki id dinamis, jadi ketika saya harus menggunakan kembali div, saya menghapus () peta yang ada untuk melepaskan memori (walaupun masih ada beberapa peristiwa yang terjadi) dan kemudian menggambar ulang div dengan id yang berbeda jadi saya membuat peta baru di dalamnya.

Saya juga menyimpan semua peta saya di suatu objek, jadi saya bisa memanipulasinya sesuai dengan id-nya (saya terkadang memiliki lebih dari satu peta yang terlihat, semuanya dengan id dinamis)

Sesuai percobaan saya dengan selebaran, peristiwa apa pun (mis. moveend, movestart, dll.) yang dimanipulasi oleh pengembang, mengubah perilaku default mereka dan tetap berada di memori saat membongkar selebaran dari dom.
Saya telah melakukan ini: @moveend="()=>{enableRecenter = true}" dan karenanya, handler 'moveend' tetap berada di memori saat membongkar/menghapus peta.
Saya menghapus manipulasi (implementasi saya sendiri) dari metode ini dari komponen peta itu sendiri dan sekarang kesalahan ini berhenti muncul.

Jadi pada dasarnya, JANGAN SENTUH METODE PETA!!! Tentu saja, kecuali, perpustakaan mendeteksi perilaku ini dan memperbaiki bug ini.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

gdbd picture gdbd  ·  3Komentar

zdila picture zdila  ·  3Komentar

onethread picture onethread  ·  3Komentar

arminghm picture arminghm  ·  3Komentar

walterfn2 picture walterfn2  ·  4Komentar