首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TypeError: this._map为空(Vue.js 3,传单)

TypeError: this._map为空(Vue.js 3,传单)
EN

Stack Overflow用户
提问于 2021-01-31 16:49:17
回答 2查看 1.5K关注 0票数 3

我从一个Vue.js项目(版本3)的传单中得到了一个奇怪的错误。

如果关闭弹出窗口并放大/缩小,则在Firefox上会出现此错误:

Uncaught : this._map为空

在Chrome上:

无法读取null的属性“_latLngToNewLayerPoint”

地图组件如下:

代码语言:javascript
复制
<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: '&copy; <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>

如何再现错误:

https://stackblitz.com/edit/vue-gjeznj

  • Close
  1. Open stackblitz:
  2. Zoom in/out

能不能只是个窃听器?或者代码中有我遗漏的错误吗?

EN

Stack Overflow用户

发布于 2021-03-18 15:03:23

FWIW,这似乎是一个新的问题,因为Vue 3。

在Vue版本2中没有这个问题,并附有传单:https://codesandbox.io/s/fast-firefly-lqmwm?file=/src/components/HelloWorld.vue

为了确保,这里是CodeSandbox:https://codesandbox.io/s/laughing-mirzakhani-sgeoq?file=/src/components/HelloWorld.vue上使用相同代码( Vue version 3 )的问题的再现

罪魁祸首似乎是Vue代理this.map,这似乎干扰了传单事件(Un)的绑定。它看起来像Vue 3现在自动执行深度代理,而Vue 2是浅的。

https://v3.vuejs.org/api/basic-reactivity.html#markraw所述

...下面的shallowXXX API允许您选择性地选择退出默认的深反应/只读转换,并在状态图中嵌入原始的、非代理的对象。它们可因各种原因而使用:

  • 某些值根本不应该是反应性的,例如复杂的第三方类实例或Vue组件对象.

...which是传单生成的map对象的例子。

一个非常简单的解决方法是不使用this.map (即不将已构建的map对象存储在组件状态,以防止Vue代理它),而只是在本地存储它(例如,const map = L.map()myLayer.addTo(map))。

但是,如果我们确实需要存储map对象,通常是为了以后可以重用它,例如,如果我们想在用户操作上添加一些层,该怎么办?

然后,在使用传单之前,确保正确地展开/取消代理this.map,例如使用Vue 3 toRaw utility function

返回reactivereadonly代理的原始对象。这是一个转义舱口,可用于临时读取而不引起代理访问/跟踪开销,或写入而不触发更改。

代码语言:javascript
复制
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:
        '&copy; <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();
    },
  },
}

演示:https://codesandbox.io/s/priceless-colden-g7ju9?file=/src/components/HelloWorld.vue

票数 3
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65981712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档