【发布时间】:2021-05-16 13:25:14
【问题描述】:
你好社区
我有一个包含子组件的父组件,其中具有不同控件的表单从 JSON 对象(通过 Axios 的 Get 请求获得)动态呈现。
我的目标是从父组件读取/循环在子组件中找到的所有表单字段值。我将如何使用 Vue JS 来做到这一点?
这是代码的一部分,如果有人提出改进建议,他们将受到好评。例如,更好地组织我的代码,使其更有条理和干净,或者使用 Vue 的最佳编程实践。谢谢。
父组件
<template>
<div id="app">
<h1>{{msg}}</h1>
<b-container>
<b-card>
<b-card-title>Formulario Dinámico</b-card-title>
<b-card-body>
<FormControls :fields="fields"></FormControls>
</b-card-body>
<b-card-footer>
<button class="btn btn-primary" @click="send">Enviar</button>
</b-card-footer>
</b-card>
</b-container>
</div>
</template>
<script>
import FormControls from "./FormControls.vue";
import ComponentTest from "./ComponentTest.vue";
import axios from 'axios';
export default {
name: 'app',
components: {
FormControls,
ComponentTest
},
created() {
axios.get('./src/form.json').then(response => this.fields = response.data);
},
data () {
return {
msg: 'Bienvenido',
fields: [] // Array que almacenará el json proveniente de la petición get
}
},
methods: {
send: () => {
alert('Enviar Formulario');
}
}
}
</script>
JSON
[
{
"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": "roles",
"label": "Roles",
"type": "select",
"sortedByKey": false,
"options": [{
"name": "admin",
"label": "Administrador"
},
{
"name": "user",
"label": "Usuario"
},
{
"name": "guest",
"label": "Invitado"
}
]
},
{
"name": "description",
"label": "Descripción",
"type": "textarea"
},
{
"name": "multiSelect",
"label": "Selección Multiple",
"type": "multiselect",
"options": [{
"name": "op1",
"label": "Opcion1"
},
{
"name": "op2",
"label": "Opcion2"
},
{
"name": "op3",
"label": "Opcion3"
}
]
}
]
子组件
<template>
<div>
<form>
<ul>
<li v-for="field in fields" :key="field">
<label :for="field.name">{{field.label}}</label>
<input v-if="isInput(field.type)"
:id="field.name" :type="field.type" :placeholder="field.placeholder" >
<select v-else-if="field.type === 'select'" :name="field.name">
<option v-for="opt in field.options" :key="opt" :value="opt.name">
{{opt.label}}
</option>
</select>
<textarea v-else-if="field.type === 'textarea'" :id="field.name" />
<div v-else-if="field.type === 'multiselect'" class="multi-select">
<multiselect v-model="values" tag-placeholder="Agregar etiqueta" :placeholder="field.placeholder" label="label" track-by="name" :options="field.options" :multiple="true" :taggable="true" @tag="agregarEtiqueta"></multiselect>
</div>
</li>
</ul>
</form>
</div>
</template>
<script>
export default {
props: ['fields'],
name: 'FormControls',
data () {
return {
titulo: 'Formulario Dinámico',
// Aqui va lo del MultiSelect
values: [],
options: []
}
},
methods: {
isInput(type) {
return ['text', 'password', 'checkbox', 'file', 'date'].includes(type);
},
// metodo multiselect
agregarEtiqueta (newTag) {
const tag = {
name: newTag,
label: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
},
devolverControl(){
}
}
}
</script>
【问题讨论】:
-
子组件循环遍历自己的字段可能更有意义。它可以发射一个带有任何结果的对象。
-
你可以看看 Vue 公式库,它非常灵活,可以从 Json 模式生成表单。
标签: javascript html json vue.js templates