Maison  >  Article  >  interface Web  >  Méthode Vue+ElementUI pour réaliser un rendu dynamique et une configuration visuelle des formulaires

Méthode Vue+ElementUI pour réaliser un rendu dynamique et une configuration visuelle des formulaires

亚连
亚连original
2018-05-31 17:53:0914275parcourir

Cet article présente principalement la méthode de Vue+ElementUI pour réaliser le rendu dynamique et la configuration visuelle des formulaires. Les amis qui en ont besoin peuvent s'y référer

Le rendu dynamique signifie avoir des données asynchrones, qui ressemblent à ceci :

{
 "inline": true,
 "labelPosition": "right",
 "labelWidth": "",
 "size": "small",
 "statusIcon": true,
 "formItemList": [
 {
 "type": "input",
 "label": "姓名",
 "disable": false,
 "readonly": false,
 "value": "",
 "placeholder": "请输入姓名",
 "rules": [],
 "key": "name",
 "subtype": "text"
 },
 {
 "type": "radio",
 "label": "性别",
 "value": "",
 "button": false,
 "border": true,
 "rules": [],
 "key": "gender",
 "options": [
 {
  "value": "1",
  "label": "男",
  "disabled": false
 },
 {
  "value": "0",
  "label": "女",
  "disabled": false
 }
 ]
 }
 ]
}

Ensuite, vous devez restituer le json comme ceci :

Les données finales du formulaire soumis ressemblent à ceci :

{
 "name": "Genji",
 "gender": "1"
}

Ensuite, nous Le but est d'encapsuler un tel composant :

<dynamic-form :config="someConfig" v-model="someData" />

Mise en œuvre

Avant de commencer, vous devez savoir comment v -model fonctionne :

<input v-model="something">

Ceci n'est que du sucre syntaxique pour l'exemple suivant :

<input
 :value="something"
 @input="something = $event.target.value">

Après avoir compris cela, implémentons ce composant étape par étape.

Tout d'abord, transférez la configuration à el-form :

<template>
 <el-form 
 class="dynamic-form" 
 :inline="formConfig.inline" 
 :model="value" 
 :label-position="formConfig.labelPosition" 
 :label-width="formConfig.labelWidth" 
 :size=&#39;formConfig.size&#39; 
 :status-icon="formConfig.statusIcon">
 <slot/>
 </el-form>
</template>
<script>
export default {
 props: {
 formConfig: {
 type: Object,
 required: true
 },
 value: {
 type: Object,
 required: true
 }
 },
}
</script>

Deuxièmement, définissez la valeur par défaut.

Parce que chaque form-item nécessite un v-model, chaque champ est garanti d'avoir une valeur avant le rendu. Une chose à noter ici est que le composant ne doit pas modifier directement le prop transmis par le composant parent, nous utilisons donc {...this.value} pour le copier rapidement ici, et enfin n'oublions pas d'en informer le composant parent. Le code est le suivant :

export default {
 props: {
 formConfig: {...},
 value: {...},
 },
 methods: {
 setDefaultValue() {
 const formData = { ...this.value }
 // 设置默认值
 this.formConfig.formItemList.forEach(({ key, value }) => {
 if (formData[key] === undefined || formData[key] === null) {
  formData[key] = value
 }
 })
 this.$emit(&#39;input&#39;, formData)
 }
 },
 mounted() {
 this.setDefaultValue()
 },
}

La troisième étape consiste à restituer l'élément de formulaire.

Comment restituer les données suivantes dans l'élément el-form-item familier ?

{
 "type": "input",
 "label": "姓名",
 "disable": false,
 "readonly": false,
 "value": "",
 "placeholder": "请输入姓名",
 "rules": [],
 "key": "name",
 "subtype": "text"
}

La première façon est d'utiliser le composant intégré de vue, qui peut s'écrire comme ceci :

<el-form-item>
 <component :is="`el-${item.type}`" />
</el-form-item>

La deuxième façon est d'utiliser v-if pour en juger un par un :

<el-form-item>
 <el-input v-if="item.type === &#39;input&#39;" />
 <span v-else>未知控件类型</span>
</el-form-item>

Considérant que la logique de traitement de chaque contrôle de formulaire est très différente, l'auteur a adopté la deuxième méthode.

Selon cette idée, nous encapsulons un dynamic-form-item , recevons un élément et restituons un élément de formulaire el :

<template>
 <el-form-item :rules="item.Rules" :label="item.label" :prop="item.key">
 <el-input 
 v-if="item.type===&#39;input&#39;" 
 v-bind="$attrs" v-on="$listeners" 
 :type="item.subtype" 
 :placeholder="item.placeholder" 
 :disabled="item.disable" 
 :readonly="item.readonly" 
 :autosize="item.autosize"></el-input>
 <el-select 
 v-else-if="item.type===&#39;select&#39;" 
 v-bind="$attrs" v-on="$listeners"
 :multiple="item.multiple" 
 :disabled="item.disabled" 
 :multiple-limit="item.multipleLimit">
  <el-option 
  v-for="o in item.options" 
  :key="o.value" 
  :label="o.label" 
  :value="o.value" 
  :disabled="o.disabled">
  </el-option>
 </el-select>
 <!--突然有点想念JSX-->
 ...
 <span v-else>未知控件类型</span>
 </el-form-item>
</template>
<script>
export default {
 props: {
 item: {
 type: Object,
 required: true
 }
 }
}
</script>

conseils : utilisez v-bind="$attrs" v-on="$listeners" pour transférer facilement le parent Pour la directive v-model du composant, voir Composants d'ordre supérieur Vue pour plus de détails.

Enfin, nous pouvons boucler pour générer un formulaire complet :

<dynamic-form-item
 v-for="item in formConfig.formItemList"
 :key="item.key"
 v-if="value[item.key]!==undefined"
 :item="item"
 :value="value[item.key]"
 @input="handleInput($event, item.key)" />

v-model="value[item.key]" ne peut pas être utilisé ici. Comme mentionné ci-dessus, les accessoires ne peuvent pas être modifiés directement dans le composant, donc ici nous. Ou transmettez-le.

methods: {
 handleInput(val, key) {
 // 这里element-ui没有上报event,直接就是value了
 this.$emit(&#39;input&#39;, { ...this.value, [key]: val })
 },
 setDefaultValue() {...}
},

Adresse complète du code : src/components/dynamic-form/form.vue

Fonctions étendues

1. , limitez le nombre de décimales

element-ui n'a pas cette fonction, mais je pense que c'est assez courant, j'ai donc utilisé el-input pour encapsuler manuellement un numéro d'entrée :

<!--普通使用-->
<input-number 
 v-model="someNumber"
 :min="1" 
 :max="99" 
 :decimal1="2" 
 append="元"></input-number>
<!--在dynamic-form-item中的应用-->
<input-number 
 v-else-if="item.type===&#39;number&#39;" 
 v-bind="$attrs" v-on="$listeners" 
 :min="item.min" 
 :max="item.max" 
 :decimal1="item.decimal1" 
 :append="item.append" 
 :prepend="item.prepend" 
 :disabled="item.disabled"></input-number>

Code complet : src/components/dynamic-form/input-number.vue

Vérification asynchrone

Merci. avec async-validator, nous pouvons facilement personnaliser les règles de validation.

Dans la configuration

{
 "type": "input",
 ...
 "rules":[
  {
   "sql": "SELECT {key} FROM balabala",
   "message": "xx已被占用",
   "trigger": "blur"
  }
 ]
}

Dans le composant dynamic-form-item , parcourez item.rules et convertissez la vérification SQL en une fonction de validation personnalisée :

<template>
 <el-form-item :rules="Rules" >
  ...
 </el-form-item>
</template>
<script>
import request from &#39;@/utils/request&#39;
export default {
 props: {
 item: {...}
 },
 computed: {
 Rules() {
  const rules = this.item.rules
  if (rules === undefined) return undefined
  const R = []
  rules.forEach(rule => {
  if (rule.sql) {
   const validator = (rule2, value, callback) => {
   // 根据项目自行修改
   request(&#39;/api/validate&#39;, &#39;POST&#39;, {
    key: rule2.field,
    value,
    sql: rule.sql.replace(/{key}/ig, rule2.field)
   })
    .then(res => {
    callback(!res || undefined)
    })
    .catch(err => {
    this.$message.error(err.message)
    callback(false)
    })
   }
   R.push({ validator, message: rule.message, trigger: &#39;blur&#39; })
  } else {
   R.push(rule)
  }
  })
  return R
 }
 },
}
</script>

3. Configuration rapide des provinces et des villes

Merci à l'auteur de element-china-area-data.

En configuration :

{
 "type": "cascader",
 ...
 "areaShortcut": "provinceAndCityData"
}

Dans le composant Dynamic-form-item :

<template>
 <el-form-item>
  ...
  <el-cascader 
   :options="item.options || require(&#39;element-china-area-data&#39;)[item.areaShortcut]"
   ></el-cascader>
 </el-form-item>
</template>

4. Options de chargement à distance

Inclus mais non. limité à la radio, case à cocher, cascader, sélectionnez

Dans la configuration :

{
 "type": "checkbox",
 ...
 "optionsUrl": "/api/some/options"
}

Dans le composant Dynamic-form-item :

<template>
 <el-form-item>
  ...
  <el-select>
   <el-option 
    v-for="o in item.options || ajaxOptions"
    ></el-option>
  </el-select>
 </el-form-item>
</template>
<script>
import request from &#39;@/utils/request&#39;
export default {
 props: {
 item: {...}
 },
 computed: {...},
 data() {
 return {
  ajaxOptions: []
 }
 },
 created() {
 const { optionsUrl, key, type } = this.item
 if (optionsUrl) {
  // 根据项目自行修改
  request(`${optionsUrl}?key=${key}`, &#39;GET&#39;)
  .then(res => {
   this.ajaxOptions = res
  })
  .catch(err => { this.$message.error(err.message) })
 }
 }
}
</script>

Ce qui précède, c'est moi que j'ai compilé pour tout le monde, j'espère que cela sera utile à tout le monde à l'avenir.

Articles connexes :

Exemple de méthode nodejs pour se connecter à la base de données mongodb

Sélectionner la méthode de vérification multi-sélection du sélecteur dans iview

Utilisation d'Axios Element pour implémenter la méthode de chargement de requête globale

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn