因此,我从一个可变的 HTML 字符串开始,它是我的用户在 RichText 编辑器中创建的 UI 模板(保存到磁盘上的 XML 文件)。它始终是有效的 XHTML。 XML 可以像这样简单:
<div>{{FORM_PLACEHOLDER}}</div>
或者像这样复杂的东西:
<div id="user-customized-content">
<h1 class="display-1">Customized Header</h1>
<p class="mb-3">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
<strong>laboris nisi ut aliquip</strong> ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<div class="alert alert-info">
<p>Laboris nisi ut <em>aliquip</em> ex ea commodo consequat</p>
</div>
<h3 class="display-4">Lorem ipsum dolor:</h3>
<form>{{FORM_PLACEHOLDER}}</form>
<p class="mb-3">
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim
id est laborum.
</p>
</div>
但它总是有{{FORM_PLACEHOLDER}}
XML 字符串中的某处。这将指定 HTML 表单应放置在 HTML 包装器代码中的确切位置。
在我的 SPA 应用程序中(我们使用 Vue.js,但我认为使用的框架/库并不重要),我通过 axios 调用检索 HTML,然后我需要将 XHTML 写入在我的交互式表单周围页面(示例如下所示)。
在 Vue.js 中,我们为此使用“插槽”。因此,父组件中将包含表单,而其子组件(下例中的 HtmlWrapper
)将包含一个环绕表单的插槽。
<template>
<HtmlWrapper>
Name: <input type="text" name="Name" v-validate="'required'" /><br />
Email: <input type="email" name="Email" /><br />
<button @click="dofunction()">Submit Form</button>
</HtmlWrapper>
</template>
<script>
import HtmlWrapper from "@/components/HtmlWrapper.vue"
</script>
我已经尝试过但不起作用的方法:
- 在占位符和 injecting the HTML 上拆分 HTML 字符串直接在表单字段的上方和下方。这没有用,因为如果使用 Vue 或 JS 将它们添加到 DOM,顶部的标签将自动关闭。
- Converting the XML string to
XmlDocument
in C# and then serializing it to JSON传递给 javascript。这非常有效,使我能够遍历 json 以围绕<slot></slot>
tag 构建 HTML但后来我意识到,相同类型的多个 HTML 标记会被分组到数组中,这会破坏它们在页面上出现的顺序。
我认为需要发生的是我需要遍历 XHTML 字符串,递归地逐个标记,并在页面上创建每个 javascript 元素,然后当我点击占位符时,我创建插槽那时(这在 Vue.js 中很容易做到:this.$slots.default
)。如果不需要(一路上犯了所有最初的错误),我宁愿不重新发明轮子,所以如果有一种方法已经存在并且可用,或者有某种组件可以做到这一点,那就太好了。否则,为我指明正确的方向将是无价的。 TIA。
最佳答案
我不确定你是否可以提供 Vue 组件动态模板。不过,我觉得你想要的可以通过Vue3的teleport来完成。虽然感觉有点棘手,但它确实有效。
我的想法是通过 v-html 呈现 XHTML,然后将您的内容传送到特定元素中,例如 #target
.
如果可能,我建议更换 {{FORM_PLACEHOLDER}}
通过类似 <div id="target"></div>
的方式利用瞬移。
<template>
<div id="example-code">
<!-- use v-html to render the template -->
<div v-html="template" />
<!-- use teleport to push content to #target which will be mounted by v-html above -->
<teleport
v-if="initialized"
to="#target"
>
Name: <input type="text" name="Name" v-validate="'required'" /><br />
Email: <input type="email" name="Email" /><br />
<button @click="dofunction()">Submit Form</button>
</teleport>
</div>
</template>
<script>
import { nextTick, onMounted, ref } from 'vue'
export default {
setup() {
const initialized = ref(false)
// for easier explaining, I create a #target div directly in the string
// Otherwise, it should be an empty string: ref('') here
const template = ref('<div id="target"></div>')
onMounted(async () => {
// The 2 lines below are just my assumtion the way you get the XHTML string
// const {data} = await axios.get('/template.html')
// template.value = data
// use the nextTick to make sure the template is rendered
nextTick(() => {
initialized.value = true
})
})
return {
initialized,
template,
}
}
}
</script>
即使 {{FORM_PLACEHOLDER}}
必须出现在模板字符串中,我们可以使用replace
将其替换为 <div id="target"></div>
:
str = "<form>{{FORM_PLACEHOLDER}}</form>"
re = /\{\{FORM_PLACEHOLDER\}\}/
str.replace(re, '<div id="target"></div>"')
// '<form><div id="target"></div>"</form>'
因为这个 XHTML 字符串存储为 ref
,v-html 内容将相应更新。那么表单内容可以是teleported
正如预期的那样。
希望能给大家带来更多新意~
关于javascript - 如何使用 javascript 获取 XHTML 字符串并将其呈现在网页上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70050421/