我正在制作一个表单生成器,它使用其中的组件作为输入字段、按钮等。我希望能够根据我传递给它的选项来生成表单。
但我无法让它渲染组件。
我尝试返回纯 HTML,但这不会渲染组件。
我从 Home.vue 模板中调用表单生成器,我希望表单具有如下所示的选项对象:
options: {
name: {
type: 'input',
label: 'Name'
},
submit: {
type: 'button',
label: 'Send'
}
}
在模板中:
<template>
<form-generator :options="options"></form-generator>
</template>
在表单生成器组件中,我尝试了多种方法,例如:
<template>
{{ generateForm(this.options) }}
// ... or ...
<div v-html="generateForm(this.options)"></div>
</template>
我包括所有组件,例如:
import {
FormButton,
FormInput
} from './FormComponents'
现在最后一部分是如何制作
FormInput
渲染?
这不起作用,因为它按字面输出 HTML:
methods: {
generateForm(options) {
// .. do stuff with options ..
var form = '<form-input />'
return form
}
}
Vue 有一种非常简单的生成动态组件的方法:
<component :is="dynamicComponentName"></component>
所以我建议你将选项定义为数组并将类型设置为组件名称:
options: [
{
type: 'FormInput',
propsData: {label: 'Name'}
},
{
type: 'FormButton',
propsData: {label: 'Send'}
}
]
然后在表单生成器中使用它,如下所示:
<component :is="option.type" v-for="option in options"></component>
您还可以像传递给任何其他组件一样传递属性,但由于它是动态的并且每个组件都有一组不同的属性,因此我会将其作为对象传递,并且每个组件都将访问它需要的数据:
<component :is="option.type" v-for="option in options" :data="option.propsData"></component>
更新
由于您无法控制组件,因此需要更多操作:
对于每个需要文本的组件,在选项中添加文本属性:
options: [
{
type: 'FormInput',
propsData: {label: 'Name'}
},
{
type: 'FormButton',
text: 'Send',
propsData: {label: 'Send'}
}
]
然后只需在组件中使用它即可:
<component :is="option.type" v-for="option in options">{{option.text}}</component>
对于传递属性,我认为你可以使用 v-bind 传递它,然后它会自动解构它们,所以如果一个按钮接受 2 个属性:
rounded, color
选项如下所示:
{
type: 'FormButton',
text: 'Button',
propsData: {rounded: true, color: '#bada55'}
}
然后是组件:
<component :is="option.type" v-for="option in options" v-bind="option.propsData">{{option.text}}</component>
你可以像这样创建一个数组:
components_data: [
{
name: 'checkbox',
data: false
},
{
name: 'text',
data: 'Hello world!'
}
]
然后在
<component>
: 内循环遍历这个数组
<component
v-for="(component,i) in components_data"
:key="i"
:is="component.name"
:data="component.data"
/>
这将动态创建 2 个组件
[<text>, <checkbox>]
并通过 props 为它们提供数据。
当您像这样推送新数据时
components_data.push({name:'image',data: {url:'cat.jpg'}})
它将呈现一个新组件为<image :data="{url:'cat.jpg'}"/>
@tomer的回答真的很好。我认为这是正确的。
就我而言,我们有一个特殊的 Vite 配置,要求我传递实际组件实例,而不是通过组件名称的字符串:
import FormInput from '@components/form/FormInput'
import FormButton from '@components/form/FormButton'
options: [
{
type: FormInput,
propsData: {label: 'Name'}
},
{
type: FormButton,
propsData: {label: 'Send'}
}
]
<component :is="option.type" v-for="option in options"></component>