tre*_*con 8 leaflet vue.js vuejs3
我在 Vue.js 项目(版本 3)中从 Leaflet 收到一个奇怪的错误。
如果我关闭弹出窗口并放大/缩小,Firefox 上会出现此错误:
未捕获的类型错误:this._map 为 null
在 Chrome 上:
无法读取 null 的属性“_latLngToNewLayerPoint”
地图组件如下:
<template>
<div id="map"></div>
</template>
<script>
import "leaflet/dist/leaflet.css";
import L from 'leaflet';
export default {
name: 'Map',
data() {
return {
map: null
}
},
mounted() {
this.map = L.map("map").setView([51.959, -8.623], 12);
L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(this.map);
L.circleMarker([51.959, -8.623]).addTo(this.map)
.bindPopup('I am a marker')
.openPopup();
}
}
</script>
<style scoped>
#map {
height: 300px;
width: 100%;
}
</style>
Run Code Online (Sandbox Code Playgroud)
如何重现错误:
这可能只是一个错误吗?或者我错过了代码中的任何错误?
FWIW,这似乎是 Vue 3 以来的一个新问题。
带 Leaflet 的 Vue 版本 2 中不存在该问题:https://codesandbox.io/s/fast-firefly-lqmwm ?file=/src/components/HelloWorld.vue
为了确保这一点,这里是 CodeSandbox 上使用相同代码但 Vue 版本 3 的问题重现: https: //codesandbox.io/s/laughing-mirzakhani-sgeoq ?file=/src/components/HelloWorld.vue
罪魁祸首似乎是this.mapVue 的代理,它似乎干扰了 Leaflet 事件(取消)绑定。看起来 Vue 3 现在会自动执行深度代理,而 Vue 2 则很浅。
如https://v3.vuejs.org/api/basic-reactivity.html#markraw中所述:
[...]下面的shallowXXX API 允许您有选择地选择退出默认的深度反应/只读转换,并将原始的、非代理的对象嵌入到状态图中。它们的用途有多种:
- 有些值根本不应该是响应式的,例如复杂的第 3 方类实例或 Vue 组件对象。
...这是 Leaflet 构建对象的情况map。
一个非常简单的解决方法是不使用this.map(即不将Leaflet构建的map对象存储在组件状态中,以防止Vue代理它),而是将其存储在本地(例如const map = L.map()然后myLayer.addTo(map))。
但是,如果我们确实需要存储地图对象(通常是为了以后可以重复使用它),例如,如果我们想在用户操作上添加一些图层,该怎么办?
然后确保在将其与 Leaflet 一起使用之前正确解开/取消代理,例如使用 Vue 3 实用函数:this.maptoRaw
reactive返回代理的原始对象readonly。这是一个逃生舱口,可用于临时读取而不产生代理访问/跟踪开销或写入而不触发更改。
import { toRaw } from "vue";
export default {
name: "Map",
data() {
return {
map: null,
};
},
mounted() {
const map = L.map("map").setView([51.959, -8.623], 12);
L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution:
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);
L.circleMarker([51.959, -8.623])
.addTo(map)
.bindPopup("I am a marker")
.openPopup();
this.map = map;
},
methods: {
addCircleMarker() {
L.circleMarker([
51.959 + Math.random() * 0.05,
-8.623 + Math.random() * 0.1,
])
.addTo(toRaw(this.map)) // Make sure to "unproxy" the map before using it with Leaflet
.bindPopup("I am a marker")
.openPopup();
},
},
}
Run Code Online (Sandbox Code Playgroud)
演示:https ://codesandbox.io/s/priceless-colden-g7ju9?file=/src/components/HelloWorld.vue
| 归档时间: |
|
| 查看次数: |
3082 次 |
| 最近记录: |