欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Vue構(gòu)建動(dòng)態(tài)表單生成器的實(shí)現(xiàn)步驟

 更新時(shí)間:2025年04月17日 10:16:48   作者:杜松混合茉莉的風(fēng)  
在前端開發(fā)中,表單是非常常見的交互元素,然而,當(dāng)表單的結(jié)構(gòu)和字段需要根據(jù)不同的業(yè)務(wù)場(chǎng)景動(dòng)態(tài)變化時(shí),手動(dòng)編寫每個(gè)表單的代碼會(huì)變得非常繁瑣,所以我們可以使用Vue實(shí)現(xiàn)一個(gè)動(dòng)態(tài)表單生成器,本文將詳細(xì)介紹實(shí)現(xiàn)動(dòng)態(tài)表單生成器的原理,需要的朋友可以參考下

引言

在前端開發(fā)中,表單是非常常見的交互元素。然而,當(dāng)表單的結(jié)構(gòu)和字段需要根據(jù)不同的業(yè)務(wù)場(chǎng)景動(dòng)態(tài)變化時(shí),手動(dòng)編寫每個(gè)表單的代碼會(huì)變得非常繁瑣。Vue 作為一個(gè)流行的前端框架,提供了強(qiáng)大的組件化和動(dòng)態(tài)渲染能力,結(jié)合 Vuelidate 庫(kù)進(jìn)行表單校驗(yàn),我們可以輕松實(shí)現(xiàn)一個(gè)動(dòng)態(tài)表單生成器。本文將詳細(xì)介紹實(shí)現(xiàn)動(dòng)態(tài)表單生成器的原理,并通過實(shí)戰(zhàn)演示如何使用 Vue 構(gòu)建一個(gè)靈活的動(dòng)態(tài)表單。

原理分析

動(dòng)態(tài)組件渲染

Vue 提供了component標(biāo)簽,通過 :is 屬性可以動(dòng)態(tài)指定要渲染的組件。結(jié)合 v-for 指令,我們可以遍歷 JSON 配置對(duì)象,根據(jù)配置中的組件類型動(dòng)態(tài)渲染不同的表單項(xiàng)。例如:

<template>
  <div v-for="item in formConfig" :key="item.name">
    <label :for="item.name">{{ item.name }}</label>
    <component :is="getComponent(item.type)"
      v-model="formData[item.name]"
      v-bind="item.props" 
    />
  </div>
</template>

在上述代碼中,getComponent 方法根據(jù) item.type 返回對(duì)應(yīng)的組件,從而實(shí)現(xiàn)動(dòng)態(tài)渲染。

表單校驗(yàn)

為了確保用戶輸入的數(shù)據(jù)符合業(yè)務(wù)規(guī)則,我們需要對(duì)表單進(jìn)行校驗(yàn)。Vuelidate 是一個(gè)輕量級(jí)的 Vue 表單驗(yàn)證庫(kù),它提供了豐富的驗(yàn)證規(guī)則和便捷的使用方式。我們可以根據(jù) JSON 配置中的 rule 字段動(dòng)態(tài)生成校驗(yàn)規(guī)則,并使用 useVuelidate 函數(shù)對(duì)表單數(shù)據(jù)進(jìn)行校驗(yàn)。例如:

const getRules = () => {
  const rules = {};
  formConfig.value.forEach(i => {
    if (i.rule) {
      rules[i.name] = {};
      if (i.rule.required === 'required') {
        rules[i.name].required = required;
      }
      if (i.rule.maxLength) {
        rules[i.name].maxLength = maxLength(i.rule.maxLength);
      } 
      if (i.rule.minLength) {
        rules[i.name].minLength = minLength(i.rule.minLength);
      } 
    }
  });
  return rules;
};
const rules = getRules();
const v$ = useVuelidate(rules, formData);

插槽機(jī)制實(shí)現(xiàn)自定義表單項(xiàng)

Vue 的插槽機(jī)制允許我們?cè)诮M件內(nèi)部預(yù)留一些位置,讓使用者可以自定義插入內(nèi)容。在動(dòng)態(tài)表單生成器中,我們可以使用具名插槽,讓用戶自定義表單的提交按鈕或其他特定的表單項(xiàng)。例如:

<template>
  <form @submit.prevent="handleSubmit">
    <!-- 動(dòng)態(tài)渲染表單項(xiàng) -->
    <div v-for="item in formConfig" :key="item.name">
      <label :for="item.name">{{ item.name }}</label>
      <component :is="getComponent(item.type)"
        v-model="formData[item.name]"
        v-bind="item.props" 
      />
    </div>
    <slot name="submit">
      <button @click="handleSubmit">submit</button>
    </slot>
  </form>
</template>

實(shí)戰(zhàn)演示

項(xiàng)目初始化

首先,我們需要?jiǎng)?chuàng)建一個(gè)新的 Vue 項(xiàng)目,并安裝所需的依賴。可以使用 Vite 快速搭建項(xiàng)目:

npm init vite@latest dynamic-form -- --template vue
cd dynamic-form
npm install
npm install @vuelidate/core @vuelidate/validators

編寫組件

1. DynamicForm.vue 組件

該組件是動(dòng)態(tài)表單生成器的核心組件,負(fù)責(zé)解析 JSON 配置并渲染表單。同時(shí),增加了表單數(shù)據(jù)提交和處理的邏輯。

<template>
  <form @submit.prevent=handleSubmit>
    
    <div v-for="item in formConfig" :key="item.name">
    
      <label :for="item.name">{{ item.name }}</label>
      <component :is="getComponent(item.type)"
      v-model="formData[item.name]"
      v-bind="item.props" 
      />
    </div>
    <slot name="submit">
      <button @click="handleSubmit">submit</button>
    </slot>
  </form>
</template>

<script setup>
import {reactive, ref}  from 'vue'
import { useVuelidate } from '@vuelidate/core'
import { required,maxLength } from '@vuelidate/validators'
import textRenderer from './TextRenderer.vue'
import selectRenderer from './SelectRenderer.vue'
import dateRenderer from './DateRenderer.vue'
const formData=reactive({})
const props = defineProps({
  formConfigJSON:{
    type:String,
    required:true,
    validator: (configJSON) =>{
      const config=JSON.parse(configJSON)
      return config.every((i)=>'name' in i && 'type' in i)
    }, 
  }
})

const formConfig=ref(JSON.parse(props.formConfigJSON))



const componentTypeMap={
  'text':textRenderer,
  'select':selectRenderer,
  'date-range':dateRenderer,
}
const getComponent=(type)=>{
  return componentTypeMap[type]
}

const handleSubmit = () => {
  v$.value.$validate();
  if (v$.value.$invalid) {
    console.log('表單驗(yàn)證不通過', v$.value.$errors);
    return;
  }
  console.log('Form submitted:', formData)

}

const getRules=()=>{
 const rules={}
 formConfig.value.forEach(i=>{
  if(i.rule){
    rules[i.name]={}
    if(i.rule.required==='required'){
      rules[i.name].required=required
    }
    if (i.rule.maxLength) {
      rules[i.name].maxLength = maxLength(i.rule.maxLength)
    } 
    if (i.rule.minLength) {
      rules[i.name].minLength = minLength(i.rule.minLength)
    } 
  }
  })
  console.log('Rules:', rules)
 return rules
}
const rules=getRules()
const v$ = useVuelidate(rules, formData);

</script>



<style scoped>
form {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

div {
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

label {
  font-weight: 500;
  color: #333;
  font-size: 14px;
}

input, select {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  width: 100%;
  box-sizing: border-box;
}

input:focus, select:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

button {
  padding: 10px 20px;
  background-color: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

button:hover {
  background-color: #66b1ff;
}
</style>

2. TextRenderer.vue 組件

該組件用于渲染文本輸入框。

<script setup>
defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
</script>
<template>
  <input type="text" :value="modelValue" @input="emit('update:modelValue', $event.target.value)">
</template>
<style scoped></style>

3. SelectRenderer.vue 組件

該組件用于渲染下拉選擇框。

<script setup>
defineProps(['modelValue', 'selections']);
const emit = defineEmits(['update:modelValue']);
</script>
<template>
  <select :value="modelValue" @change="emit('update:modelValue', $event.target.value)">
    <option v-for="item in selections" :key="item.value" :value="item.value">{{ item.selection }}</option>
  </select>
</template>
<style scoped></style>

錯(cuò)誤記錄

defineEmits 使用錯(cuò)誤defineEmits 接收的參數(shù)應(yīng)該是一個(gè)數(shù)組,這里沒有使用數(shù)組包裹事件名。

@select 事件使用錯(cuò)誤:在 <select> 元素上,通常使用 @change 事件來監(jiān)聽選擇項(xiàng)的變化,而不是 @select

4. DateRenderer.vue 組件

該組件用于渲染日期選擇框。

<script setup>
defineProps(['modelValue']);
const emit = defineEmits(['update:modelValue']);
</script>
<template>
  <input type="date" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)">
</template>
<style scoped></style>

使用動(dòng)態(tài)表單組件

在 App.vue 中使用 DynamicForm 組件,并傳入 JSON 配置。

<script setup>
import { ref } from 'vue';
import DynamicForm from './components/DynamicForm.vue';
const config = [
  {
    "name": "username",
    "type": "text",
    "rule": {"required": "required"},
  },
  {
    "name": "userid",
    "type": "text",
    "rule": {"required": "required", "maxLength": "6"},
  },
  {
    "name": "date",
    "type": "date-range",
    "rule": { "required": "required" },
  },
  {
    "name": "gender",
    "type": "select",
    "props": {
      "selections": [
        { "value": "male", "selection": "male" },
        { "value": "female", "selection": "female" }
      ]
    },
    "rule": { "required": "required" },
  }
];
const configJSON = JSON.stringify(config);
</script>
<template>
  <DynamicForm :formConfigJSON="configJSON"/>
</template>
<style scoped></style>

問題

@submit.prevent

在 Vue.js 中,@submit.prevent 是一個(gè)事件綁定語(yǔ)法。 @submit 用于監(jiān)聽 HTML 表單的 submit 事件,當(dāng)用戶提交表單(比如點(diǎn)擊表單內(nèi)的提交按鈕)時(shí)會(huì)觸發(fā)該事件。 .prevent 是一個(gè)修飾符,它的作用是調(diào)用 event.preventDefault() 方法,阻止表單的默認(rèn)提交行為。在默認(rèn)情況下,表單提交會(huì)導(dǎo)致頁(yè)面刷新,使用 .prevent 修飾符后就可以避免頁(yè)面刷新,從而讓開發(fā)者可以在 JavaScript 中自定義處理表單提交的邏輯,比如通過 AJAX 發(fā)送表單數(shù)據(jù)到服務(wù)器等。 例如:

<template> <form @submit.prevent="handleSubmit"> 
<input type="text" v-model="formData.name"> <input type="submit" value="提交"> 
</form> 
</template> 
<script> 
export default { 
data() 
{ return { formData: { name: '' } }; 
}, 
methods: { handleSubmit() { 
// 在這里處理表單提交的邏輯,比如發(fā)送數(shù)據(jù)到服務(wù)器 console.log('表單提交了', this.formData); } 
} 
}; 
</script> 

在上述代碼中,@submit.prevent 會(huì)阻止表單的默認(rèn)提交行為,然后調(diào)用 handleSubmit 方法來處理表單提交。

component標(biāo)簽是怎么用的

在不同的前端框架里, 標(biāo)簽的使用方式有所不同,下面主要介紹 Vue.js 和 React 中 標(biāo)簽的使用。

Vue.js 里 標(biāo)簽的使用

在 Vue.js 中, 標(biāo)簽是一個(gè)動(dòng)態(tài)組件,可依據(jù)不同條件來渲染不同的組件。

基本用法

你可以借助 :is 綁定一個(gè)組件名或者組件選項(xiàng)對(duì)象,以此來動(dòng)態(tài)渲染組件。

錯(cuò)誤用法

'text': 'InputRenderer', 
'select': 'SelectRenderer', 
'date-range': 'DateRangeRenderer'

解釋

  • :is 綁定的 currentComponent 是一個(gè)變量,其值為組件名。

  • 當(dāng)點(diǎn)擊按鈕時(shí),currentComponent 的值會(huì)發(fā)生改變,從而動(dòng)態(tài)渲染不同的組件。

input的type有哪些

v-bind綁定對(duì)象

v-bind="item.props" 是對(duì)象展開寫法,會(huì)自動(dòng)將item.props對(duì)象中的每個(gè)屬性綁定為組件的props。 完整語(yǔ)法是 v-bind:attributeName="expression"

    
<component 
  :is="getComponent(item.type)" 
  v-model="formData[item.name]" 
  v-bind="item.props" />
    其中item.props={
      selections: [
        { value: male, selection: male },
        { value: female, selection: female }
      ]
    }
  v-bind="item.props"等價(jià)于v-bind:selections=item.props.selections

總結(jié)

通過以上步驟,我們成功實(shí)現(xiàn)了一個(gè) Vue 動(dòng)態(tài)表單生成器。利用 Vue 的動(dòng)態(tài)組件渲染、表單校驗(yàn)和插槽機(jī)制,我們可以根據(jù)不同的 JSON 配置動(dòng)態(tài)生成表單,并對(duì)用戶輸入的數(shù)據(jù)進(jìn)行校驗(yàn)。同時(shí),增加了表單數(shù)據(jù)提交和處理的邏輯,模擬了將表單數(shù)據(jù)發(fā)送到后端的過程。這種方式大大提高了表單開發(fā)的靈活性和可維護(hù)性,減少了重復(fù)代碼的編寫。

以上就是使用Vue構(gòu)建動(dòng)態(tài)表單生成器的實(shí)現(xiàn)步驟的詳細(xì)內(nèi)容,更多關(guān)于Vue動(dòng)態(tài)表單生成器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 從eleUI的Loading知道了單例模式的用法

    從eleUI的Loading知道了單例模式的用法

    這篇文章主要介紹了從eleUI的Loading知道了單例模式的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 分享一個(gè)精簡(jiǎn)的vue.js 圖片lazyload插件實(shí)例

    分享一個(gè)精簡(jiǎn)的vue.js 圖片lazyload插件實(shí)例

    本篇文章主要介紹了分享一個(gè)精簡(jiǎn)的vue.js 圖片lazyload插件實(shí)例。非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2017-03-03
  • vue?this.$router.go(-1);返回時(shí)如何帶參數(shù)

    vue?this.$router.go(-1);返回時(shí)如何帶參數(shù)

    這篇文章主要介紹了vue?this.$router.go(-1);返回時(shí)如何帶參數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Vue中的computed和watch用法及區(qū)別

    Vue中的computed和watch用法及區(qū)別

    Vue中的computed和watch都可以監(jiān)聽數(shù)據(jù)變化,但computed主要用于計(jì)算派生屬性,而watch則用于監(jiān)聽特定數(shù)據(jù)變化并執(zhí)行回調(diào)函數(shù)。兩者使用時(shí)需要注意區(qū)別
    2023-04-04
  • 傻瓜式vuex語(yǔ)法糖kiss-vuex整理

    傻瓜式vuex語(yǔ)法糖kiss-vuex整理

    kiss-vuex 是一個(gè)非常簡(jiǎn)單的語(yǔ)法糖類庫(kù),這篇文章主要介紹了傻瓜式vuex語(yǔ)法糖kiss-vuex整理,非常具有實(shí)用價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • vue3.0生命周期的示例代碼

    vue3.0生命周期的示例代碼

    這篇文章主要介紹了vue3.0生命周期的相關(guān)知識(shí),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-09-09
  • uniapp前端支付篇之微信、抖音、快手、h5四個(gè)平臺(tái)支付功能

    uniapp前端支付篇之微信、抖音、快手、h5四個(gè)平臺(tái)支付功能

    支付功能在我們?nèi)粘i_發(fā)中經(jīng)常會(huì)遇到,下面這篇文章主要給大家介紹了關(guān)于uniapp前端支付篇之微信、抖音、快手、h5四個(gè)平臺(tái)支付功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • 快速理解Vue路由導(dǎo)航守衛(wèi)

    快速理解Vue路由導(dǎo)航守衛(wèi)

    這篇文章主要介紹了快速理解Vue路由導(dǎo)航守衛(wèi),“導(dǎo)航”表示路由正在發(fā)生變化,vue-router?提供的導(dǎo)航守衛(wèi)主要用來通過跳轉(zhuǎn)或取消的方式守衛(wèi)導(dǎo)航。有多種機(jī)會(huì)植入路由導(dǎo)航過程?中:全局的,?單個(gè)路由獨(dú)享的,?或者組件級(jí)的,下面來快速來接具體內(nèi)容吧
    2021-12-12
  • vue3獲取、設(shè)置元素高度的代碼舉例

    vue3獲取、設(shè)置元素高度的代碼舉例

    這篇文章主要給大家介紹了關(guān)于vue3獲取、設(shè)置元素高度的相關(guān)資料,小編通過實(shí)際案例向大家展示操作過程,操作方法簡(jiǎn)單易懂,需要的朋友可以參考下
    2024-08-08
  • M1 pro芯片啟動(dòng)Vue項(xiàng)目的方法步驟

    M1 pro芯片啟動(dòng)Vue項(xiàng)目的方法步驟

    本文主要介紹了M1 pro芯片啟動(dòng)Vue項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11

最新評(píng)論