sac*_*mar 5 javascript svg leaflet vue.js vuejs3
我正在开发一个 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>
Run Code Online (Sandbox Code Playgroud)
该组件基本上呈现一个内部有文本的圆圈。如果我在主组件的模板部分中使用此组件,如下所示,那么它可以正常工作(显然)
主组件.vue
<template>
<circle-with-text-svg />
</template>
Run Code Online (Sandbox Code Playgroud)
但我想将此 SVG 组件渲染输出作为选项发送给第三方。
真实用例:-实际上,我创建了这个单独的组件以在我的传单地图上显示为标记。现在的问题是我想在 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]
});
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后它给出了错误
支持实验性语法“JSX 当前未启用”
在react中,我们可以正常地在另一个组件的模板中使用该组件。但是我们如何在 vue.js 中实现这一点
通过查看错误,似乎 JSX 实验未启用。
有人可以告诉我如何实现这一目标吗?
好的,所以在评论中我推荐了问题How to get the generated html content of a component in vuejs that is 实际上为Vue 2实现的答案
我很好奇这是否适用于 Vue 3,你可以看到下面的结果。以下是需要进行的更改:
new Vue并createApp使用global h()而不是传递给render()$mount()不带参数调用主 Vue 实例的函数。这是有效的,因为 Vue 创建了要挂载到内存中的 DOM 元素。Vue 3 中不是这种情况 - 您需要自己提供元素app.component()时无法访问。tempApp所有使用中的组件都必须在适当的实例中注册 - 请参阅迁移指南// 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')Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@3.1.4/dist/vue.global.js"></script>
<div id='app'>
</div>Run Code Online (Sandbox Code Playgroud)
注1:上面的代码旨在直接在import不可用的浏览器中运行。因此,我们使用 Vue 全局构建并使用例如Vue.createApp或来访问 Vue 全局 API Vue.h。在常规 Vue 应用程序中,您需要将这些函数导入为import { createApp, h } from 'Vue'
注 2:可以说,如果与 Leaflet 组件一起使用的 HTML 片段与您的CircleWithTextSvg组件一样简单,那么将它们定义为模板文字而不是 Vue 组件会更简单且更高效