0

我正在尝试使用其中的动态信息创建 Google 地图标记。对于该功能,我使用带有 SVG 作为模板的 Vuejs-Component 并添加"text"-Tag

例子:

<template>
    <svg width="40px" height="56px" viewBox="0 0 40 56" version="1.1" xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink">
        <text>{{ text }}</text>
    </svg>
</template>

<script>
    export default {
        name: "DynamicGMapMarker",
        props: {
            text: {
                type: String,
                required: true
            }
        }
    }
</script>

然后我通过一个辅助函数创建 SVG 并创建一个 base64 数据 url:

import Vue from 'vue'
import DynamicGMapMarker from './DynamicGMapMarker'

const DynamicGMapMarkerConstructor = Vue.extend(DynamicGMapMarker)

export const getDynamicMarkerIcon = (text) => {
    const iconComponent = new DynamicGMapMarkerConstructor({
        propsData: {
            text
        }
    });
    iconComponent.$mount();
    const iconDom = iconComponent.$el;
    const iconString = new XMLSerializer().serializeToString(iconDom);
    return 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(iconString);
}

现在,我可以使用该getDynamicMarkerIcon()功能了。这适用于vue.js,但不适用于nuxt.js。在 nuxt.js 中,我们需要从 npm 添加一个 XML-Serializer,因为 nuxt 不能使用浏览器的 XMLSerializer。为此,我正在使用teclone/xml-serializer

现在,问题似乎是 Nuxt 无法创建 DOM,因为 SSR。当我尝试使用此方法时:

<template>
    <div id="app">
        <GmapMap
                :center="center"
                :zoom="15"
                :options="options"
                id="map"
        >
            <GmapCluster :zoomOnClick="true">
                <GmapMarker
                        :key="index"
                        v-for="(marker, index) in markers"
                        :position="marker.coordinates"
                        :clickable="true"
                        :draggable="false"
                        :title="marker.name"
                        :icon="getMarker(marker)"
                />
            </GmapCluster>
        </GmapMap>
    </div>
</template>

<script>
    import GmapCluster from 'vue2-google-maps/dist/components/cluster'
    import {getMarkerIcon} from "./MapIconUtil"

    export default {
        name: 'App',
        components: {
            GmapCluster
        },
        methods: {
            getMarker(marker) {
                return getDynamicMarkerIcon(marker.text);
            }
        },
        data() {
            return {
                options: {
                    zoomControl: false,
                    mapTypeControl: false,
                    scaleControl: false,
                    streetViewControl: false,
                    rotateControl: false,
                    fullscreenControl: false,
                    disableDefaultUi: true,
                    clickableIcons: false
                },
                center: {
                    lat: 11,
                    lng: 11
                },
                "markers": [
                    {
                        coordinates: {
                            name: "Test",
                            lat: 11.0001,
                            lng: 11.0001,
                            text: "101"
                        }
                    }
                ]
            }
        }
    }
</script>

我收到一个iconComponent.$el未定义的错误。我无法在 DOM 中安装 SVG。

有没有可能告诉 Nuxt,这个组件应该只在浏览器端运行?

我已经尝试过GmapMarker使用<client-only>-Tag。那没有用。我可以使用“虚拟 DOM”之类的东西吗?任何其他想法如何使它工作?

4

1 回答 1

0

我做的。您可以选择性地更改 nuxt 将呈现特定 url 的“模式”。在这里您可以看到哪些配置是可能的。

您必须创建一个服务器中间件并告诉 nuxt 是否应该在spa中呈现路径。否则,只需默认为您在nuxt.config.js中指定的模式。

看看这个例子。

于 2020-08-06T05:44:50.150 回答