带有No-SSR的Vue2-Leaflet导致未定义窗口错误

时间:2018-10-31 01:38:02

标签: vue.js leaflet nuxt.js ssr

我一直在尝试很多东西。我尝试过nuxt-leaflet依赖关系,我尝试过编写自己的插件并将其包含在内。但是,一切都以“未定义窗口”错误结尾。

该地图只能在客户端上加载。

我的Vue组件:

 <template>
        <no-ssr>
            <l-map
                    id="map"
                    :zoom="zoom"
                    :min-zoom="3"
                    :center="center"
            >

            </l-map>
        </no-ssr>
 </template>

<script lang="ts">
    import Vue from 'vue';
    import {latLng, marker} from 'leaflet';
    import {ExploreItemType} from '~/components/explore/ExploreItem';
    import {Component} from "nuxt-property-decorator";

    @Component()
    export default class ExplorerMap extends Vue {

        url = 'https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoia2dydWVuZWJlcmciLCJhIjoiY2puajJ3c3dmMGV1YzNxbDdwZ3Y5MXc0bCJ9.kuHo67NUkzqya1NtSjTYtw';
        attribution = 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>';
        zoom = 3;
        center = latLng(51.505, -0.09);
        drawCluster = true;

    }
</script>

所以我在plugins / vue-leaflet.ts中编写了自己的插件

import Vue from 'vue'
import Vue2Leaflet from 'vue2-leaflet'
import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster';

Vue.component('l-circle', Vue2Leaflet.LCircle);
Vue.component('l-geo-json', Vue2Leaflet.LGeoJson);
Vue.component('l-icon-default', Vue2Leaflet.LIconDefault);
Vue.component('l-layer-group', Vue2Leaflet.LLayerGroup);
Vue.component('l-map', Vue2Leaflet.LMap);
Vue.component('l-marker', Vue2Leaflet.LMarker);
Vue.component('l-popup', Vue2Leaflet.LPopup);
Vue.component('l-tile-layer', Vue2Leaflet.LTileLayer);
Vue.component('l-tooltip', Vue2Leaflet.LTooltip);

并将其包含在nuxt.config.js中

{src: "~/plugins/vue-leaflet.ts", ssr: false}

无论我尝试了什么,我总是最终会遇到未定义窗口的错误。我没主意了。

2 个答案:

答案 0 :(得分:1)

这是因为您在组件中做

import {latLng, marker} from 'leaflet';

可能会进行一些窗口检查并立即失败。因此,您需要使用if (process.client)检查

有条件地导入它

答案 1 :(得分:1)

多亏了Aldarund的提示,我才开始工作:

<template>

    <div>
        <no-ssr>
            <l-map
                    id="map"
                    :zoom="zoom"
                    :min-zoom="3"
                    :center="center"
            >
                <l-tile-layer :url="url" :attribution="attribution"/>
               ....
            </l-map>
        </no-ssr>
    </div>
</template>

<script lang="ts">
    const isBrowser = typeof window !== 'undefined';
    let leaflet;
    if (isBrowser) {
        leaflet = require('leaflet');
    }
    import Vue from 'vue';

    import {Component, Prop, Watch} from "nuxt-property-decorator";

    @Component({})
    export default class ExplorerMap extends Vue {

        url = 'https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoia2dydWVuZWJlcmciLCJhIjoiY2puajJ3c3dmMGV1YzNxbDdwZ3Y5MXc0bCJ9.kuHo67NUkzqya1NtSjTYtw';
        attribution = 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>';
        zoom = 3;
        center;

        created() {
            if (isBrowser) {
                this.center = leaflet.latLng(51.505, -0.09);
            }
....
}