我正在 Vue 3 中开发一个动态仪表板,用户可以在其中为他们想要呈现的部分指定简单的类似 XML 的模板。
我希望 XML 中与特定 Vue 组件名称匹配的节点呈现为 Vue 组件,而其他节点应呈现为普通 HTML。
例如,一个 XML 模板可能如下所示:
<Dashboard>
<Elements>
<div class="title">Switches</div>
<Switches device="kitchen-bulb" />
</Elements>
</Dashboard>
<div>
<Elements>
内部应该呈现为普通 HTML(我已经通过利用 <slot>
并将节点内容传递给 v-html
组件上的 <Elements>
实现了这一点),而 <Switches>
,与特定导入的 Vue 组件的名称相匹配,应呈现为 Vue 组件 - 在本例中为 device
从模板传递的属性。
现在的代码是这样的:
/// index.js
import Switch from './Switch'
export default {
Switch,
}
/// Elements.vue
<template>
<div class="elements">
<div class="container" v-html="content" />
</div>
</template>
<script>
import elements from './index'
export default {
name: "Elements",
props: {
content: {
type: String,
},
},
mounted() {
const content = new DOMParser()
.parseFromString(`<div>${this.content}</div>`, 'text/html')
.childNodes[0]
Object.entries(elements).forEach(([name, element]) => {
this.$options.components[name] = element
const nodes = content.getElementsByTagName(name);
[...nodes].forEach((node) => {
const renderedComponent = magicStringToRenderedHTMLStringOrDOM(element, node)
node.parentElement.replaceChild(renderedComponent, node)
})
})
this.content = content.childNodes[0].innerHTML
},
}
</script>
content
是<Elements>
的节点内容由父组件传递给组件。
我需要的是填充 magicStringToRenderedHTMLStringOrDOM
的东西调用它,给定 Vue 组件定义、节点表示和属性,呈现我可以在 content
中简单替换的 Vue 组件并用 v-html
渲染.
我知道 Vue 2 曾经提供 something similar with Vue.compile
.我发现显然做类似事情的唯一 Vue 3 函数是 createRenderer
,但我还没有找到很多如何使用它的例子。
最佳答案
我已经通过使用 native render
函数解决了这个问题,并为每个与索引上的动态组件匹配的标签动态安装了一个应用程序。
从头开始编译和渲染模板比重新发明轮子更好:)
/// Content of index.js
import Switch from './Switch'
export default {
Switch,
}
/// Content of Elements.vue
<template>
<div class="elements">
<div class="container" ref="container" />
</div>
</template>
<script>
import elements from './index'
export default {
name: "Elements",
props: {
content: {
/**
* Example content property:
* <div>
* <h1>Switches</h1>
* <Switches />
* </div>
*/
type: String,
},
},
mounted() {
this.$refs.container.innerHTML = this.content
// Iterate over all the dynamic components on index.js
Object.entries(elements).forEach(([name, element]) => {
// Dynamically load each of them
this.$options.components[name] = element;
// Get all the tags on the content DOM that match
// a certain dynamic component
[...this.$refs.container.getElementsByTagName(name)].forEach((component) => {
// Replace each of them with a new Vue app
// that renders the component and mounts it
// on the DOM node
createApp({
render() { return h(element) }
}).mount(component)
})
})
}
}
</script>
关于javascript - 如何在运行时在 Vue 3 中将组件呈现为其 HTML 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66717511/