如何在 Vue 中从 JSON 构建动态 HTML 控件?
Posted
技术标签:
【中文标题】如何在 Vue 中从 JSON 构建动态 HTML 控件?【英文标题】:How to build dynamic HTML controls in Vue from a JSON? 【发布时间】:2021-05-11 15:45:08 【问题描述】:美好的一天社区。p>
我需要您的帮助,以便在 VUE 中从 JSON 动态构建 html 控件。
目前我完成了一个练习,我有一个 html 模板,它根据 JSON 中设置的参数呈现输入控件列表。但是我想构建更多控件,而不仅仅是输入控件。
export default
name: 'app',
data ()
return
msg: 'Hola Mundo',
fields: [
"name": "fechaRegistro",
"label": "Fecha de Registro",
"type": "date",
"placeholder": 'Ingresa Fecha'
,
"name": "nombreDeUsuario",
"label": "Nombre de Usuario",
"type": "text",
"placeholder": "Ingresa Usuario"
,
"name": "passwordUsuario",
"label": "Password",
"type": "password",
"placeholder": "Contraseña"
,
"name": "adjuntarArchivo",
"label": "Adjuntar",
"type": "file"
,
"name": "activo",
"label": "Activo",
"type": "checkbox"
,
"name": "roles",
"label": "Roles",
"type": "multiSelect",
"sortedByKey": false,
"options": [
"name": "admin",
"label": "Admin"
,
"name": "user",
"label": "User"
,
"name": "guest",
"label": "Invitado"
]
]
#app
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
h1, h2
font-weight: normal;
ul
list-style-type: none;
padding: 0;
li
display: inline-block;
margin: 0 10px;
a
color: #42b983;
<template>
<div id="app">
<h1>msg</h1>
<form>
<ul id="controles">
<li v-for="field in fields" :key="field">
<label :for="field.name">field.label</label>
<input :id="field.name" :type="field.type" :placeholder="field.placeholder">
</li>
</ul>
</form>
</div>
</template>
我的目标是在 Json 中接收我应该构建的控件类型及其参数。比如json里来了select类型的控件,我必须建一个select,如果来了一个textarea类型的控件,我必须建一个textarea等等。
请留下您的解决方案,谢谢。
【问题讨论】:
【参考方案1】:您需要提前知道预期的字段类型。你可以像这样创建一个方法hasInputTag
:
methods:
hasInputTag(type)
return ['text', 'password', 'file', 'date'].includes(type);
然后检查v-for
循环中的field.type
并渲染适当的元素,例如:
<li v-for="field in fields" :key="field">
<label :for="field.name">
field.label
</label>
<input
v-if="hasInputTag(field.type)"
:name="field.name"
:type="field.type"
>
<select
v-else-if="field.type === 'select'"
:name="field.name"
>
<option v-for="opt in field.options">
// etc.
</option>
</select>
<textarea
v-else-if="field.type === 'textarea'"
:name="field.name"
>
</li>
更新 1:
如果你想使用单独的组件,你可以在你的模板中做这样的事情:
<component
:is="getComponentName(field.type)"
v-bind="field"
/>
您的getComponentName
方法可能如下所示(其中每个组件都有一个名称,例如Custom_input
、Custom_checkbox
等,并且您已将它们导入到父级中):
getComponentName(type)
if (['text', 'password', 'file', 'date'].includes(type)) return 'Custom_input';
return `Custom_$type`;
更新 2:
为了存储每个组件的值,我会在父级中创建一个fieldValues
对象并像这样初始化它:
fieldValues: this.fields.reduce((res, field) =>
res[field.name] = null;
return res;
, )
然后在你的循环中使用v-model="fieldValues[field.name]"
。
【讨论】:
很好的答案,现在我有一个问题——如何将每个 html 控件分隔在不同的组件中并根据条件调用它们?谢谢 我已经更新了我的示例来展示如何做到这一点 谢谢,我已经开发了一个解决方案,但是我有一个问题,如何从所有表单字段中检索数据?我想遍历字段并将它们的值保存在数组中?我可以使用 v-model,但是如何将它应用于动态生成的控件,这些控件在渲染之前一直存在? 我已经添加了一个关于我将如何做到这一点的建议。 我正在尝试从动态生成的字段中检索值。你告诉我我应该在父组件中创建一个变量来存储表单字段的值,但是子组件如何将值存储在父组件的那个对象中?我必须使用 $emit 吗?使用vuex作为中介是否可取?以上是关于如何在 Vue 中从 JSON 构建动态 HTML 控件?的主要内容,如果未能解决你的问题,请参考以下文章
IOS - 如何在 Swift 3 中从 JSON 中捕获动态数组维度