将VUE3组件呈现为html字符串

wz8daaqr  于 2021-09-23  发布在  Java
关注(0)|答案(1)|浏览(1403)

我正在从事vue.js项目(版本3)。在这种情况下,我希望将组件的呈现html视图用于当前组件的方法。
我在vue项目中创建了以下svg组件。
circlewithtextsvg.vue

<template>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" width="20" height="20">
        <g id="UrTavla">
            <circle cx="10" cy="10" r="10" stroke="gray" stroke-width="1" :fill="fill" />
            <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="1px" dy=".3em">{{text}}</text>
        </g>
    </svg>
</template>

<script>
    export default {
        props: {
            text: { 
                type: String, 
                default: "1"
            },
            fill: { 
                type: String, 
                default: "white"
            }
        }
    }
</script>

该组件基本上渲染一个内有文本的圆。如果我在我的主组件的模板部分使用这个组件,如下面所示,那么它可以正常工作(显然)
maincomponent.vue

<template>
    <circle-with-text-svg />
</template>

但是我想将这个svg组件呈现的输出作为选项发送给第三方。
实际用例:-实际上,我创建了这个单独的组件,以在传单Map上显示为标记。现在的问题是,我想在maincomponent的方法中使用这个svg组件,这样我就可以将它用作l.divicon的一个选项
当我尝试以下方法时

export default {
    methods: {
        generateMap(element) {
            // ...
            let icon = L.divIcon({ 
                html: <circle-with-text-svg 
                    fill="'#D3D5FF'"
                    text="1" />, 
                iconSize: [10, 10]
            });
            // ...
        }
    }
}

然后给出了误差
当前未启用对实验语法“jsx”的支持
在react中,我们可以简单地在另一个组件的模板内正常使用该组件。但是我们如何在vue.js中实现这一点呢
通过查看错误,似乎没有启用jsx实验。
有人能告诉我我如何才能做到这一点?

byqmnocz

byqmnocz1#

好的,在评论中,我推荐了一个问题的答案,即如何在vuejs中获取组件的编译html内容,该组件实际上是为vue 2实现的
我很好奇这是否适用于VUE3,您可以看到下面的结果。以下是所需的更改:
明显的变化正在取代 new Vue 具有 createApp 使用global h()代替传递到 render() 在vue 2中,您可以调用 $mount() 不带参数的主vue示例的函数。这是因为vue创建了dom元素以装载到内存中。vue 3中不是这种情况-您需要自己提供元素
在我的示例中没有使用一个大的变化,但对于某些用例来说非常重要的是,在vue 3中,在主应用程序示例中注册为全局的组件使用 app.component() 无法在中访问 tempApp 用于呈现html。所有正在使用的组件都必须在相应的示例中注册-请参阅迁移指南

// We use component options object with string template
// In the proper Vue app (with Webpack and Vue SFC) this whole block can be replaced with "import CircleWithTextSvg from CircleWithTextSvg.vue"
const CircleWithTextSvg = {
  name: 'CircleWithTextSvg',
  props: {
    text: {
      type: String,
      default: "1"
    },
    fill: {
      type: String,
      default: "white"
    }
  },
  template: `
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" width="20" height="20">
        <g id="UrTavla">
            <circle cx="10" cy="10" r="10" stroke="gray" stroke-width="1" :fill="fill" />
            <text x="50%" y="50%" text-anchor="middle" stroke="black" stroke-width="1px" dy=".3em">{{text}}</text>
        </g>
    </svg>
  `
}

const app = Vue.createApp({
  mounted() {
    console.log(this.getIconHtml('Hello!'))
  },
  methods: {
    getIconHtml(text, type) {
      const tempApp = Vue.createApp({
        render() {
          return Vue.h(CircleWithTextSvg, {
            text,
            type
          })
        }
      })

      // in Vue 3 we need real element to mount to unlike in Vue 2 where mount() could be called without argument...
      const el = document.createElement('div');
      const mountedApp = tempApp.mount(el)

      return mountedApp.$el.outerHTML
    }
  }
})

app.mount('#app')
<script src="https://unpkg.com/vue@3.1.4/dist/vue.global.js"></script>
<div id='app'>
</div>

注1:上述代码旨在直接在浏览器中运行,其中 import 没有。因此,我们使用vue全局构建并访问vue全局api,例如 Vue.createAppVue.h . 在常规vue应用程序中,您需要将这些功能作为 import { createApp, h } from 'Vue' 注2:如果与传单组件一起使用的html框架像您的 CircleWithTextSvg 组件,更简单、更有效的方法是将它们定义为模板文本,而不是vue组件

相关问题