<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
已知的需要動態控制的場景:
請優先考慮風格二的封裝方式
特點簡介
將el-form, el-form-item, el-input等等完全封裝到動態表單元件內,通過for迴圈來刷表單項,外部通過傳json設定物件的方式,完成欄位的動態顯示/隱藏控制。
優點:
<el-form-item><el-input></el-input></el-form-item>
這類程式碼的重複編寫缺點:
v-bind=attrs
和v-on=evts
方式進行設定,這相對於template語法來說,json物件的設定方式,就沒那麼讓vue開發者習慣了。v-bind=attrs
方式設定原元件的屬性,那麼如果想設定一些預設值就變得麻煩起來,因為vue2中,設定了v-bind=attrs
之後,沒法再在模板中設定預設屬性,必須在這個封裝的元件中,在獲取到設定物件時,進行一些比較繁瑣的初始值設定。程式碼實現範例
動態表單元件
<template> <el-form :model="formModel" v-bind="elFormAttrs"> <el-form-item v-for="(formItemConfig, index) in formItemConfigArr" :key="`${formItemConfig.prop}-${index}`" :prop="formItemConfig.prop" :rules="formItemConfig.rules" > <template #label> <div class="o-custom-label">{{ formItemConfig.label }}</div> </template> <el-input v-if="formItemConfig.itemType === 'input'" v-model="formModel[formItemConfig.prop]" ></el-input> <el-select v-else-if="formItemConfig.itemType === 'select'" v-model="formModel[formItemConfig.prop]" > <template v-if="formItemConfig.optionArr"> <el-option v-for="(option, pos) in formItemConfig.optionArr" :key="`${option.value}-${pos}`" :value="option.value" :label="option.label" ></el-option> </template> </el-select> </el-form-item> </el-form> </template> <script> export default { name: "DynForm", model: { event: "change", prop: "formData", }, props: { formData: { type: Object, }, /** * prop: 唯一標識 * itemType: 表單項型別 * rules: 表單驗證規則 * label: 顯示標籤 * optionArr: 下拉值 */ formItemConfigArr: { type: Array, default: () => [], }, // el-form支援的所有屬性 elFormAttrs: { type: Object, }, }, data() { return { formModel: this.formData ? this.formData : {}, }; }, watch: { // 監聽formData改變,將formData的值設定給元件內部的formModel,規避eslint對單項資料流的規則檢測報錯 formData: { handler(newVal) { this.formModel = newVal; }, }, }, methods: {}, }; </script> <style scoped></style>
呼叫動態表單元件
<template> <div class="demo-form"> <DynForm v-model="formData" :form-item-config-arr="formItemConfigArr" :el-form-attrs="elFormAttrs" ></DynForm> </div> </template> <script> import DynForm from "@/components/form/dyn/DynForm"; export default { name: "FormTemplate3", components: { DynForm, }, props: { // input文字方塊數量 count: { type: Number, default: 50, }, }, data() { // 表單項設定 const formItemConfigArr = [ { prop: "sex", label: "成語故", itemType: "select", optionArr: [], }, { prop: "name", label: "姓名", itemType: "input", }, { prop: "three", label: "成語故事", itemType: "select", optionArr: [], }, { prop: "four", label: "一二三四五", itemType: "select", optionArr: [], }, { prop: "five", label: "一二三四五六", itemType: "select", optionArr: [], }, { prop: "six", label: "一二三四五六七", itemType: "select", optionArr: [], }, { prop: "seven", label: "一二三四五六七八", itemType: "select", optionArr: [], }, { prop: "eight", label: "一二三四五六七八九", itemType: "select", optionArr: [], }, { prop: "ten", label: "ten", itemType: "select", optionArr: [], }, { prop: "zero", label: "zero", itemType: "select", optionArr: [], }, { prop: "a", label: "hello", itemType: "select", optionArr: [], }, { prop: "b", label: "hello world", itemType: "select", optionArr: [], }, { prop: "c", label: "good idea thank", itemType: "select", optionArr: [], }, { prop: "d", label: "good configuration", itemType: "select", optionArr: [], }, { prop: "d", label: "good idea thank configuration", itemType: "select", optionArr: [], }, ]; return { elFormAttrs: { inline: true, labelWidth: "81px", }, formData: null, formItemConfigArr, }; }, created() { this.loadFormData(); this.loadSexOptions(); }, methods: { loadFormData() { setTimeout(() => { this.formData = { name: "張三", sex: 1, }; }, 1000); }, loadSexOptions() { setTimeout(() => { const item = this.formItemConfigArr.find((item) => item.prop === "sex"); if (item) { const sexOptionArr = [ { value: 1, label: "選項1" }, { value: 2, label: "選項2" }, { value: 3, label: "選項3" }, ]; item.optionArr = sexOptionArr; } }, 1500); }, }, }; </script> <style scoped lang="scss"> .js-validate-form ::v-deep(.is-error .o-show-data) { color: red; } .demo-form ::v-deep(.el-form-item__label) { line-height: 1.6; display: inline-flex; height: 40px; justify-items: right; justify-content: flex-end; align-items: center; } .demo-form ::v-deep(.el-form-item__label .o-custom-label) { word-break: break-word; text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; /* 這裡是超出幾行省略 */ overflow: hidden; } </style>
特點介紹
通過函陣列件,以jsx語法對el-form-item進行封裝,僅封裝模板程式碼部分,動態部分全部由呼叫者自行實現
優點:
缺點:
程式碼實現範例
表單項元件封裝
<script> export default { functional: true, name: "DynFormItemsFunction", props: { formItemConfigArr: { type: Array, required: true, }, }, render(h, context) { // console.log(context); const { props, scopedSlots } = context; const { formItemConfigArr } = props; // 獲得插槽裡的 vNodes const vNodes = scopedSlots.default(); return vNodes.map((node, idx) => { const formItemConfig = formItemConfigArr[idx]; return ( <el-form-item prop={formItemConfig.prop} rules={formItemConfig.rules}> <span slot="label" className="o-custom-label"> {formItemConfig.label} </span> {node} </el-form-item> ); }); }, }; </script> <style scoped> .o-custom-label { color: blue; } </style>
程式碼呼叫範例
<template> <div> <el-form :model="formData" inline :validate-on-rule-change="false"> <!-- DynFormItemsFunction 這個元件,僅封裝了el-form-item的邏輯 --> <DynFormItemsFunction :form-item-config-arr="formItemConfigArrComp"> <!-- 注意元件的迴圈是在slot中進行的,el-form-item的包裝邏輯, 交給了DynFormItemsFunction元件實現 --> <template v-for="(formItemConfig, idx) in formItemConfigArrComp"> <el-input v-if="formItemConfig.itemType === 'input'" v-model="formData[formItemConfig.prop]" :key="idx" ></el-input> <el-select v-else-if="formItemConfig.itemType === 'select'" v-model="formData.sex" :key="idx" > <template v-if="formItemConfig.optionArr"> <el-option v-for="option in formItemConfig.optionArr" :key="option.value" :value="option.value" :label="option.label" ></el-option> </template> </el-select> </template> </DynFormItemsFunction> </el-form> </div> </template> <script> import DynFormItemsFunction from "@/components/form/dyn/DynFormItemsFunction"; export default { name: "FormTemplate", components: { DynFormItemsFunction, }, props: { count: { type: Number, default: 50, }, }, data() { /* 完整的表單設定放在data中,資料中的元素個數不會變, 動態值也填充到formItemConfigArr對應元素中(如性別的下拉選項值), formItemConfigArr只需要關注完整表單需要哪些表單項欄位, 以及下拉選項資料的填充,無需考慮表單項欄位的顯示/隱藏邏輯控制 */ const formItemConfigArr = [ { prop: "sex", label: "性別", itemType: "select", optionArr: [], }, { prop: "name", label: "姓名", itemType: "input", rules: [{ required: true, message: "該項必填", trigger: "change" }], }, { prop: "school", label: "學校", itemType: "input", rules: [], }, ]; // for (let i = 0; i < this.count; i++) { // formItemConfigArr.push({ // prop: "name" + i, // label: "姓名" + i, // itemType: "input", // }); // } return { formData: { name: null, sex: null, school: null, }, formItemConfigArr, }; }, computed: { /* 表單項的顯示/隱藏通過計算屬性實現,可以認為計算屬性就只關注控制哪些表單項需要顯示, 哪些需要隱藏,就可以了。算是一種職責分離 */ formItemConfigArrComp() { return this.formItemConfigArr.filter((item) => { if (this.formData.sex === 3 && item.prop === "name") { return null; } return item; }); }, }, created() { this.loadOptions(1500); }, methods: { loadOptions(timeout) { setTimeout(() => { const item = this.formItemConfigArr.find((item) => item.prop === "sex"); if (item) { const sexOptionArr = new Array(10) .fill(true) .map((item, idx) => ({ value: idx, label: "選項:" + idx })); item.optionArr = sexOptionArr; } }, timeout); }, }, }; </script> <style scoped lang="scss"> .js-validate-form ::v-deep(.is-error .o-show-data) { color: red; } </style>
到此這篇關於vue2實現封裝動態表單元件的文章就介紹到這了,更多相關vue封裝表單元件內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45