最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3+Element?Plus動(dòng)態(tài)表單實(shí)現(xiàn)

 更新時(shí)間:2025年05月15日 08:41:15   作者:滿(mǎn)  
本文主要介紹了Vue3+Element?Plus動(dòng)態(tài)表單實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

 完整代碼

<template>
  <div class="dynamic-form-container">
    <el-form
      ref="dynamicFormRef"
      :model="formData"
      :rules="formRules"
      label-width="auto"
      label-position="top"
      v-loading="loading"
    >
      <!-- 動(dòng)態(tài)渲染表單字段 -->
      <template v-for="field in formConfig" :key="field.name">
        <!-- 輸入框 -->
        <el-form-item
          v-if="field.type === 'input'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <el-input
            v-model="formData[field.name]"
            :placeholder="field.placeholder || `請(qǐng)輸入${field.label}`"
            :type="field.inputType || 'text'"
            :clearable="field.clearable !== false"
          />
        </el-form-item>

        <!-- 下拉選擇 -->
        <el-form-item
          v-else-if="field.type === 'select'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <el-select
            v-model="formData[field.name]"
            :placeholder="field.placeholder || `請(qǐng)選擇${field.label}`"
            :clearable="field.clearable !== false"
            style="width: 100%"
          >
            <el-option
              v-for="option in field.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
          </el-select>
        </el-form-item>

        <!-- 單選框 -->
        <el-form-item
          v-else-if="field.type === 'radio'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <el-radio-group v-model="formData[field.name]">
            <el-radio
              v-for="option in field.options"
              :key="option.value"
              :label="option.value"
            >
              {{ option.label }}
            </el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 復(fù)選框 -->
        <el-form-item
          v-else-if="field.type === 'checkbox'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <el-checkbox-group v-model="formData[field.name]">
            <el-checkbox
              v-for="option in field.options"
              :key="option.value"
              :label="option.value"
            >
              {{ option.label }}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>

        <!-- 日期選擇器 -->
        <el-form-item
          v-else-if="field.type === 'date'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <el-date-picker
            v-model="formData[field.name]"
            :type="field.dateType || 'date'"
            :placeholder="field.placeholder || `請(qǐng)選擇${field.label}`"
            style="width: 100%"
          />
        </el-form-item>

        <!-- 開(kāi)關(guān) -->
        <el-form-item
          v-else-if="field.type === 'switch'"
          :label="field.label"
          :prop="field.name"
        >
          <el-switch v-model="formData[field.name]" />
        </el-form-item>

        <!-- 自定義插槽 -->
        <el-form-item
          v-else-if="field.type === 'slot'"
          :label="field.label"
          :prop="field.name"
          :rules="generateFieldRules(field)"
        >
          <slot :name="field.slotName" :field="field" :model="formData" />
        </el-form-item>
      </template>

      <el-form-item>
        <el-button type="primary" @click="submitForm">提交</el-button>
        <el-button @click="resetForm">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'

// 表單引用
const dynamicFormRef = ref()

// 加載狀態(tài)
const loading = ref(false)

// 表單數(shù)據(jù)
const formData = ref({})

// 表單驗(yàn)證規(guī)則
const formRules = ref({})

// 表單配置(從后端獲取)
const formConfig = ref([
  // 默認(rèn)配置,實(shí)際會(huì)被后端數(shù)據(jù)覆蓋
  {
    name: 'username',
    label: '用戶(hù)名',
    type: 'input',
    required: true,
    placeholder: '請(qǐng)輸入用戶(hù)名'
  }
])

// 模擬從后端獲取表單配置
const fetchFormConfig = async () => {
  try {
    loading.value = true
    
    // 這里替換為實(shí)際的API調(diào)用
    const response = await mockApiGetFormConfig()
    
    formConfig.value = response.data.fields
    
    // 初始化表單數(shù)據(jù)
    initFormData()
    
    // 生成驗(yàn)證規(guī)則
    generateFormRules()
  } catch (error) {
    ElMessage.error('獲取表單配置失敗: ' + error.message)
  } finally {
    loading.value = false
  }
}

// 初始化表單數(shù)據(jù)
const initFormData = () => {
  const data = {}
  formConfig.value.forEach(field => {
    // 根據(jù)字段類(lèi)型設(shè)置默認(rèn)值
    switch (field.type) {
      case 'checkbox':
        data[field.name] = field.defaultValue || []
        break
      case 'switch':
        data[field.name] = field.defaultValue || false
        break
      default:
        data[field.name] = field.defaultValue || ''
    }
  })
  formData.value = data
}

// 生成表單驗(yàn)證規(guī)則
const generateFormRules = () => {
  const rules = {}
  formConfig.value.forEach(field => {
    if (field.required || field.rules) {
      rules[field.name] = generateFieldRules(field)
    }
  })
  formRules.value = rules
}

// 生成單個(gè)字段的驗(yàn)證規(guī)則
const generateFieldRules = (field) => {
  const rules = []
  
  // 必填規(guī)則
  if (field.required) {
    rules.push({
      required: true,
      message: field.message || `${field.label}不能為空`,
      trigger: field.trigger || 'blur'
    })
  }
  
  // 自定義規(guī)則
  if (field.rules && Array.isArray(field.rules)) {
    rules.push(...field.rules)
  }
  
  // 類(lèi)型校驗(yàn)
  if (field.type === 'input' && field.inputType === 'email') {
    rules.push({
      type: 'email',
      message: '請(qǐng)輸入正確的郵箱格式',
      trigger: ['blur', 'change']
    })
  }
  
  return rules
}

// 提交表單
const submitForm = async () => {
  try {
    // 表單驗(yàn)證
    await dynamicFormRef.value.validate()
    
    // 這里替換為實(shí)際的提交API
    const response = await mockApiSubmitForm(formData.value)
    
    ElMessage.success('提交成功')
    console.log('表單數(shù)據(jù):', formData.value)
    console.log('服務(wù)器響應(yīng):', response)
    
    // 可以在這里處理提交成功后的邏輯
  } catch (error) {
    if (error instanceof Error) {
      ElMessage.error('表單驗(yàn)證失敗: ' + error.message)
    }
  }
}

// 重置表單
const resetForm = () => {
  dynamicFormRef.value.resetFields()
}

// 模擬API獲取表單配置
const mockApiGetFormConfig = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        data: {
          fields: [
            {
              name: 'username',
              label: '用戶(hù)名',
              type: 'input',
              required: true,
              placeholder: '請(qǐng)輸入用戶(hù)名',
              maxlength: 20
            },
            {
              name: 'password',
              label: '密碼',
              type: 'input',
              inputType: 'password',
              required: true,
              placeholder: '請(qǐng)輸入密碼',
              rules: [
                { min: 6, max: 18, message: '密碼長(zhǎng)度在6到18個(gè)字符', trigger: 'blur' }
              ]
            },
            {
              name: 'gender',
              label: '性別',
              type: 'select',
              required: true,
              options: [
                { label: '男', value: 'male' },
                { label: '女', value: 'female' },
                { label: '其他', value: 'other' }
              ]
            },
            {
              name: 'hobbies',
              label: '興趣愛(ài)好',
              type: 'checkbox',
              options: [
                { label: '游泳', value: 'swimming' },
                { label: '跑步', value: 'running' },
                { label: '閱讀', value: 'reading' }
              ]
            },
            {
              name: 'subscribe',
              label: '訂閱通知',
              type: 'switch',
              defaultValue: true
            },
            {
              name: 'birthday',
              label: '出生日期',
              type: 'date',
              dateType: 'date',
              required: true
            }
          ]
        }
      })
    }, 800)
  })
}

// 模擬API提交表單
const mockApiSubmitForm = (data) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ code: 200, message: 'success', data })
    }, 500)
  })
}

// 組件掛載時(shí)獲取表單配置
onMounted(() => {
  fetchFormConfig()
})
</script>

<style scoped>
.dynamic-form-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}
</style>

后端API數(shù)據(jù)結(jié)構(gòu)建議

后端API返回的表單配置建議采用如下JSON格式:

{
  "code": 200,
  "message": "success",
  "data": {
    "fields": [
      {
        "name": "username",
        "label": "用戶(hù)名",
        "type": "input",
        "required": true,
        "placeholder": "請(qǐng)輸入用戶(hù)名",
        "inputType": "text",
        "maxlength": 20,
        "rules": [
          {
            "pattern": "^[a-zA-Z0-9_]+$",
            "message": "只能包含字母、數(shù)字和下劃線(xiàn)"
          }
        ]
      },
      {
        "name": "gender",
        "label": "性別",
        "type": "select",
        "required": true,
        "options": [
          {
            "label": "男",
            "value": "male"
          },
          {
            "label": "女",
            "value": "female"
          }
        ]
      },
      {
        "name": "subscribe",
        "label": "訂閱通知",
        "type": "switch",
        "defaultValue": true
      }
    ]
  }
}

到此這篇關(guān)于Vue3+Element Plus動(dòng)態(tài)表單實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Vue3 Element Plus動(dòng)態(tài)表單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決vue無(wú)法加載文件D:\Program Files\nodejs\node_global\vue.ps1,因?yàn)樵诖讼到y(tǒng)上禁止運(yùn)行腳本

    解決vue無(wú)法加載文件D:\Program Files\nodejs\node_global\vue.ps1,

    這篇文章主要給大家介紹了關(guān)于解決vue無(wú)法加載文件D:\Program Files\nodejs\node_global\vue.ps1,因?yàn)樵诖讼到y(tǒng)上禁止運(yùn)行腳本的相關(guān)資料,這個(gè)報(bào)錯(cuò)是由于在系統(tǒng)上禁止運(yùn)行腳本導(dǎo)致的,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • Vue?elementUI表單嵌套表格并對(duì)每行進(jìn)行校驗(yàn)詳解

    Vue?elementUI表單嵌套表格并對(duì)每行進(jìn)行校驗(yàn)詳解

    element-ui中有詳細(xì)的各種表格及表格方法,下面這篇文章主要給大家介紹了關(guān)于Vue?elementUI表單嵌套表格并對(duì)每行進(jìn)行校驗(yàn)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • 如何在 Vue3 中使用 OpenLayers 實(shí)現(xiàn)事件 loadstart 和 loadend

    如何在 Vue3 中使用 OpenLayers 實(shí)現(xiàn)事件 loadst

    在這篇文章中,我將詳細(xì)介紹如何在 Vue3 + OpenLayers 中監(jiān)聽(tīng) loadstart 和 loadend 事件,并通過(guò) Vue3 Composition API 進(jìn)行代碼優(yōu)化,使其更加高效、健壯,感興趣的朋友一起看看吧
    2025-04-04
  • Vue中如何處理token過(guò)期問(wèn)題

    Vue中如何處理token過(guò)期問(wèn)題

    這篇文章主要介紹了Vue中如何處理token過(guò)期問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Vue專(zhuān)屬狀態(tài)管理庫(kù)Pinia的使用與實(shí)踐分享

    Vue專(zhuān)屬狀態(tài)管理庫(kù)Pinia的使用與實(shí)踐分享

    在 Vue 的開(kāi)發(fā)中,狀態(tài)管理是一個(gè)不可或缺的部分,尤其是在復(fù)雜的應(yīng)用中,組件之間的狀態(tài)共享和管理變得至關(guān)重要,Pinia 作為 Vue 的專(zhuān)屬狀態(tài)管理庫(kù),本文將深入介紹 Pinia 的基礎(chǔ)知識(shí)、核心功能以及實(shí)際使用場(chǎng)景,需要的朋友可以參考下
    2024-11-11
  • 使用vue-i18n?入口文件配置控制臺(tái)報(bào)警問(wèn)題解決

    使用vue-i18n?入口文件配置控制臺(tái)報(bào)警問(wèn)題解決

    這篇文章主要介紹了使用vue-i18n?入口文件配置控制臺(tái)報(bào)警問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Vue中使用element-ui給按鈕綁定一個(gè)單擊事件實(shí)現(xiàn)點(diǎn)擊按鈕就彈出dialog對(duì)話(huà)框

    Vue中使用element-ui給按鈕綁定一個(gè)單擊事件實(shí)現(xiàn)點(diǎn)擊按鈕就彈出dialog對(duì)話(huà)框

    最近遇到了個(gè)需求是使用element-ui插件編寫(xiě)頁(yè)面,點(diǎn)擊按鈕,彈出對(duì)話(huà)框,這篇文章主要給大家介紹了關(guān)于Vue中使用element-ui給按鈕綁定一個(gè)單擊事件實(shí)現(xiàn)點(diǎn)擊按鈕就彈出dialog對(duì)話(huà)框的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Vue2.x響應(yīng)式簡(jiǎn)單講解及示例

    Vue2.x響應(yīng)式簡(jiǎn)單講解及示例

    這篇文章主要介紹了Vue2.x響應(yīng)式及簡(jiǎn)單的示例,應(yīng)用了簡(jiǎn)單的源代碼進(jìn)行講解,感興趣的小伙伴可以參考一下,希望可以幫助到你
    2021-08-08
  • vue-manage-system升級(jí)到vue3的開(kāi)發(fā)總結(jié)分析

    vue-manage-system升級(jí)到vue3的開(kāi)發(fā)總結(jié)分析

    這篇文章主要為大家介紹了vue-manage-system升級(jí)到vue3的開(kāi)發(fā)總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 淺談Vue知識(shí)系列-axios

    淺談Vue知識(shí)系列-axios

    這篇文章主要介紹了淺談Vue知識(shí)系列-axios,本文章內(nèi)容詳細(xì),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,需要的朋友可以參考下<BR>
    2023-01-01

最新評(píng)論

民权县| 化州市| 汉阴县| 大方县| 察雅县| 谷城县| 永登县| 师宗县| 乡宁县| 福泉市| 延川县| 洛南县| 平邑县| 崇文区| 桑植县| 施甸县| 沈阳市| 犍为县| 禹城市| 兴义市| 金华市| 靖西县| 镇沅| 响水县| 重庆市| 梁河县| 洮南市| 全州县| 鸡泽县| 长乐市| 邵东县| 阿城市| 鹤壁市| 罗田县| 乌什县| 自贡市| 蓬莱市| 玛沁县| 商洛市| 陈巴尔虎旗| 桐梓县|