element中el-form-item屬性prop踩坑
最近負(fù)責(zé)前后端項(xiàng)目開發(fā),有個(gè)需求是實(shí)現(xiàn)Djangorestframework(drf)+element實(shí)現(xiàn)動(dòng)態(tài)渲染form表單,drf后端提供json,前端從json中獲取form表單元素,并且綁定表單驗(yàn)證規(guī)則
在el-form-item屬性prop上遇到報(bào)錯(cuò)或者沒(méi)綁定到數(shù)據(jù),報(bào)錯(cuò)如下
[Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'prop')"
element官方文檔解釋el-form-item的prop必須是el-form屬性model的直接子屬性
后端返回?cái)?shù)據(jù)如下
{ "status": "success", "code": 200, "data": { "form_attributes": { "inline": true, "label-width": "auto", "size": "small" }, "form_data": { "name": null, "path": null, "component": null, "hidden": false, "meta": { "icon": null, "title": null }, "pid": null }, "form_item_list": [ { "type": "text", "prop": "name", "label": "菜單名", "placeholder": "請(qǐng)輸入菜單名", "rules": [ { "required": true, "message": "請(qǐng)輸入菜單名", "trigger": "blur" } ] }, { "type": "text", "prop": "path", "label": "鏈接地址", "placeholder": "'/'開頭", "rules": [ { "required": true, "message": "'/'開頭", "trigger": "blur" } ] }, { "type": "text", "prop": "component", "label": "組件", "placeholder": "參考前端組件填寫", "rules": [ { "required": true, "message": "參考前端組件填寫", "trigger": "blur" } ] }, { "type": "switch", "prop": "hidden", "label": "是否隱藏", "value": false }, { "type": "json", "prop": "meta", "item": [ { "type": "text", "prop": "icon", "label": "圖標(biāo)", "placeholder": "圖標(biāo)名字,參考前端圖標(biāo)", "rules": [ { "required": true, "message": "圖標(biāo)名字,參考前端圖標(biāo)", "trigger": "blur" } ] }, { "type": "text", "prop": "title", "label": "標(biāo)題", "placeholder": "請(qǐng)輸入菜單名", "rules": [ { "required": true, "message": "請(qǐng)輸入菜單名", "trigger": "blur" } ] } ] }, { "type": "select", "prop": "pid", "label": "父菜單", "clearable": true, "filterable": false, "multiple": false, "options": [ { "label": "系統(tǒng)管理", "value": 2 }, { "label": "用戶管理", "value": 3 }, { "label": "菜單管理", "value": 4 }, { "label": "權(quán)限管理", "value": 5 }, { "label": "角色管理", "value": 6 } ] } ] }, "message": null }
從上面可以看到form表單元素對(duì)應(yīng)的是 form_item_list,表單提交數(shù)據(jù)是 form_data,這兩個(gè)是分開,也就是el-form中model綁定是 form_data 而el-form-item遍歷的是 form_item_list,注意 form_item_list 中含有嵌套類型json,對(duì)應(yīng)的后端是json字段渲染表單,單獨(dú)提供form_data返回字段設(shè)計(jì)是為了控制前端json內(nèi)容,動(dòng)態(tài)字段中過(guò)于靈活,可以隨意修改json包含的字段和類型,所以返回字段由后端控制和校驗(yàn)
截取前端渲染表單代碼如下,注意這個(gè)時(shí)候能渲染但是rules綁定是失敗的
<!-- 添加菜單對(duì)話框 --> <el-dialog title="添加菜單" :visible.sync="addDialogVisible" width="50%" :close-on-click-modal="false" @close="addDialogClosed"> <!-- 表單內(nèi)容主體 --> <el-form ref="addFormRef" :model="formData" :size="formAttributes.size" :inline="formAttributes.inline" :label-width="formAttributes.labelWidth"> <div v-for="(item, index) in formItemList" :key="index"> <el-form-item :prop="formItemList + index + item.prop" :label="item.label" :rules="item.rules"> <!-- text輸入框 --> <el-input v-if="item.type==='text'" v-model="formData[item.prop]" clearable :placeholder="item.placeholder"></el-input> <!-- textarea輸入框 --> <el-input v-if="item.type==='textarea'" v-model="formData[item.prop]" clearable autosize :type="textarea" :placeholder="item.placeholder"></el-input> <!-- 下拉框 --> <el-select v-if="item.type==='select'" v-model="formData[item.prop]" clearable :multiple="item.multiple"> <el-option v-for="op in item.options" :key="op.value" :label="op.label" :value="op.value"></el-option> </el-select> <el-switch v-if="item.type==='switch'" v-model="formData[item.prop]" :label="item.label"></el-switch> <template v-if="item.type==='json'"> <div v-for="(json_item, json_index) in item.item" :key="json_index"> <el-form-item :prop="item.item + json_index + json_item.prop" :label="json_item.label" :rules="json_item.rules" style="margin-left: -80px;"> <!-- text輸入框 --> <el-input v-if="json_item.type==='text'" v-model="formData[item.prop][json_item.prop]" clearable :placeholder="json_item.placeholder"></el-input> <!-- textarea輸入框 --> <el-input v-if="json_item.type==='textarea'" v-model="formData[json_item.prop]" clearable autosize :type="textarea" :placeholder="json_item.placeholder"></el-input> <!-- 下拉框 --> <!-- <el-select v-if="item.type==='select'" v-model="formData[item.prop]" clearable :placeholder="item.label" :multiple="item.multiple" @change="item.change(formData[item.prop])"> --> <el-select v-if="json_item.type==='select'" v-model="formData[json_item.prop]" clearable :multiple="json_item.multiple"> <el-option v-for="op in json_item.options" :key="op.value" :label="op.label" :value="op.value"></el-option> </el-select> <el-switch v-if="json_item.type==='switch'" v-model="formData[json_item.prop]" :label="json_item.label"></el-switch> </el-form-item> </div> </template> </el-form-item> </div> </el-form> <!-- 底部 --> <el-divider></el-divider> <span slot="footer" class="dialog-footer"> <el-button @click="addDialogVisible = false">取消</el-button> <el-button type="primary" @click="addForm">確定</el-button> </span> </el-dialog>
在前端渲染無(wú)法綁定到表單規(guī)則,如下圖
經(jīng)過(guò)研究,從上面的數(shù)據(jù)結(jié)構(gòu)可以發(fā)現(xiàn),form_data 中每個(gè)元素對(duì)應(yīng)是 form_item_list 中的 prop,那么有兩個(gè)寫法可以定位
第一種寫法如下,這種寫法沒(méi)那么直觀
<!-- 普通字段渲染 --> <el-form-item :prop="item.prop" :label="item.label" :rules="item.rules"> <!-- json字段渲染 --> <el-form-item :prop="item.prop + '.' + json_item.prop" :label="json_item.label" :rules="json_item.rules" style="margin-left: -80px;">
更好的第二種寫法如下
<el-form-item :prop="formItemList[index].prop" :label="item.label" :rules="item.rules"> <el-form-item :prop="formItemList[index].prop + '.' + item.item[json_index].prop" :label="json_item.label" :rules="json_item.rules" style="margin-left: -80px;">
此時(shí)能動(dòng)態(tài)渲染表單和綁定表單項(xiàng)驗(yàn)證規(guī)則,如下圖
總結(jié):上面兩種寫法都是為了定位到表單元素對(duì)應(yīng)的表單的model直接子屬性,踩坑的原因是遍歷表單的列表(v-for)和表單提交數(shù)據(jù)(model)不是在一個(gè)對(duì)象下,尤其是遍歷表單下,還包括嵌套表單json處理,需要注意定位json提交數(shù)據(jù)
到此這篇關(guān)于element中el-form-item屬性prop踩坑 的文章就介紹到這了,更多相關(guān)element prop屬性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue cli4.0項(xiàng)目引入typescript的方法
這篇文章主要介紹了vue cli4.0項(xiàng)目引入typescript的方法,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07使用electron打包Vue前端項(xiàng)目的詳細(xì)流程
這篇文章主要介紹了使用electron打包Vue前端項(xiàng)目的詳細(xì)流程,文中通過(guò)圖文結(jié)合的方式給大家介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)electron打包Vue有一定的幫助,需要的朋友可以參考下2024-04-04簡(jiǎn)單了解vue中父子組件如何相互傳遞值(基礎(chǔ)向)
這篇文章主要介紹了簡(jiǎn)單了解vue中父子組件如何相互傳遞值(基礎(chǔ)向),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07vue+導(dǎo)航錨點(diǎn)聯(lián)動(dòng)-滾動(dòng)監(jiān)聽和點(diǎn)擊平滑滾動(dòng)跳轉(zhuǎn)實(shí)例
今天小編就為大家分享一篇vue+導(dǎo)航錨點(diǎn)聯(lián)動(dòng)-滾動(dòng)監(jiān)聽和點(diǎn)擊平滑滾動(dòng)跳轉(zhuǎn)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11Vue axios 將傳遞的json數(shù)據(jù)轉(zhuǎn)為form data的例子
今天小編就為大家分享一篇Vue axios 將傳遞的json數(shù)據(jù)轉(zhuǎn)為form data的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10Vue解決element-ui消息提示$message重疊問(wèn)題
這篇文章主要為大家介紹了Vue解決element-ui消息提示$message重疊問(wèn)題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08element?ui富文本編輯器的使用效果與步驟(quill-editor)
富文本編輯器在任何項(xiàng)目中都會(huì)用到,在Element中我們推薦vue-quill-editor組件,下面這篇文章主要給大家介紹了關(guān)于element?ui富文本編輯器的使用效果與步驟(quill-editor)的相關(guān)資料,需要的朋友可以參考下2022-10-10Vue3+TS實(shí)現(xiàn)動(dòng)態(tài)路由權(quán)限的示例詳解
當(dāng)我們?cè)陂_發(fā)一個(gè)大型的前端應(yīng)用時(shí),動(dòng)態(tài)路由權(quán)限是一個(gè)必不可少的功能,本文將介紹如何使用Vue 3和TypeScript來(lái)實(shí)現(xiàn)動(dòng)態(tài)路由權(quán)限,希望對(duì)大家有所幫助2024-01-01