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='formConfig.size' :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('input', 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 === 'input'" /> <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==='input'" 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==='select'" 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('input', { ...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==='number'" 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 '@/utils/request' 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('/api/validate', 'POST', { 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: 'blur' }) } 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('element-china-area-data')[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 '@/utils/request' export default { props: { item: {...} }, computed: {...}, data() { return { ajaxOptions: [] } }, created() { const { optionsUrl, key, type } = this.item if (optionsUrl) { // 根据项目自行修改 request(`${optionsUrl}?key=${key}`, 'GET') .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!