【问题标题】:How to build dynamic HTML controls in Vue from a JSON?如何在 Vue 中从 JSON 构建动态 HTML 控件?
【发布时间】: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等等。

请留下您的解决方案,谢谢。

【问题讨论】:

    标签: javascript html vue.js templates components


    【解决方案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_inputCustom_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作为中介是否可取?
    猜你喜欢
    • 2015-08-01
    • 1970-01-01
    • 2011-05-17
    • 2020-07-13
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多