element中form組件prop嵌套屬性的問(wèn)題解決
Introduction
分享今天同事問(wèn)的一個(gè)問(wèn)題, 下面這段代碼會(huì)報(bào)錯(cuò),先看代碼:重點(diǎn)是el-form-item組件的prop屬性
<template>
<div id="app">
<el-form label-width="100px" :model="ruleForm" :rules="rules">
<el-form-item
v-for="(item, index) in tableData"
:key="item.id"
:prop="'tableData.' + index + '.name'"
:rules="rules.name"
>
<el-input v-model="item.name"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
ruleForm: {
name: ''
},
tableData: [
{ id: 1, name: "" },
{ id: 2, name: "" },
],
rules: {
name: [
{
required: true,
message: "請(qǐng)輸入活動(dòng)名稱",
trigger: "blur",
validator(rule, value, callback) {
console.log("rule: ", rule);
console.log("value: ", value);
},
},
],
},
};
},
};
</script>我第一眼看上去的時(shí)候并沒(méi)有發(fā)現(xiàn)什么問(wèn)題,但這段代碼實(shí)實(shí)在在的報(bào)錯(cuò)了,我們來(lái)看一下錯(cuò)誤

首先需要明確的是 這是一個(gè)警告, 并非一個(gè)error, 但他直接導(dǎo)致了我們的代碼執(zhí)行結(jié)果非預(yù)期,我們來(lái)分析一下這個(gè)錯(cuò)誤
1.首先這個(gè)錯(cuò)誤的第一句**Error in mounted hook**, 錯(cuò)誤發(fā)生在mounted鉤子中
2.請(qǐng)安排一個(gè)有效的path給prop
首先第一個(gè)問(wèn)題,我的代碼中并沒(méi)有mounted函數(shù),他怎么會(huì)報(bào)錯(cuò)呢?
第二個(gè)問(wèn)題,讓我們提供一個(gè)有效的prop, 但這里我們明明給的是有效的撒。
最后查了官網(wǎng)并查了百度 都沒(méi)有找到很好的解決方式,最后沒(méi)有辦法,只能去看一下element-ui的源碼, 下面是源碼環(huán)節(jié):
1.找到packages/form/src/form-item.vue這個(gè)文件

2. 我們根據(jù)他的報(bào)錯(cuò)來(lái)分析, 首先他說(shuō)`mounted hook`中報(bào)錯(cuò), 那我們就直接來(lái)看這個(gè)hook做了什么事情:
mounted() {
if (this.prop) {
this.dispatch('ElForm', 'el.form.addField', [this]); // 這一步不用管
let initialValue = this.fieldValue; // 取得fieldvalue
// 判斷fieldvalue是不是數(shù)組, 如果是數(shù)組則合并
if (Array.isArray(initialValue)) {
initialValue = [].concat(initialValue);
}
// 給this定義一個(gè)initialValue屬性
Object.defineProperty(this, 'initialValue', {
value: initialValue
});
this.addValidateEvents();
}
}我看這段代碼的第一反應(yīng)是, 這也沒(méi)干什么事兒啊, 就取了個(gè)值 賦了個(gè)值, 看了一會(huì)兒我發(fā)現(xiàn), 有一個(gè)盲點(diǎn)就是this.fieldValue這里, 這是一個(gè)什么東西呢?不知道 去看一下。
computed: {
fieldValue() {
// 1.拿到當(dāng)前"form"的model屬性(這里很重要, 要記住這一步)
const model = this.form.model;
if (!model || !this.prop) { return; }
// 2.拿到當(dāng)前"form-item"的prop屬性,
// 也就是我們傳的那個(gè):prop="'tableData.' + index + '.name'"
let path = this.prop;
if (path.indexOf(':') !== -1) {
path = path.replace(/:/, '.');
}
// 3.將model和path傳給了getPropByPath方法
return getPropByPath(model, path, true).v;
}
}代碼翻到fieldValue這里, 發(fā)現(xiàn)這是一個(gè)computed屬性(步驟見(jiàn)注釋), 發(fā)現(xiàn)最終返回getPropByPath方法的返回結(jié)果, 我們接著去看一下這個(gè)方法.
我們發(fā)現(xiàn)這個(gè)方法是在utils/util下的一個(gè)方法

第一眼看到這個(gè)方法, 是不是有一種眼熟的感覺(jué)?越看越像js的一個(gè)面試題
function getValue(obj, path) {
...
}
const obj = { a: { b: { c: '1' } } }
getValue(obj, 'a.b.c'); // 1有木有?。?有木有!不能說(shuō)一模一樣,只能說(shuō)分毫不差,既然知道它是面試題就簡(jiǎn)單了,我們首先需要明確 這個(gè)方法的作用就是 通過(guò)嵌套字符串key 拿到key對(duì)應(yīng)的value, 那我們來(lái)看一下element是怎么做的。
首先先看第一句代碼let tempObj = obj, 這里第一次的obj是誰(shuí)呢?是不是上面?zhèn)鬟^(guò)來(lái)的this.form.model啊? 我們來(lái)看一下 我們代碼中傳輸?shù)膍odel是什么

我們這里只需要記住, 我們傳的是一個(gè)對(duì)象{ name: '' }好的 我們?cè)賮?lái)看下一步, path = 正則匹配, 最后的結(jié)果是keyArr = ['tableData', 0, 'name']下面的代碼就是走keyArr的循環(huán)了, 這里我們是3次循環(huán), 因?yàn)閗eyArr只有三個(gè)元素
我們還是來(lái)捋一下:
1. 第一次循環(huán), 此時(shí)的tempObj是 { name: '' }, key是tableData, key in tempObj?, 很顯然是false, 所以直接走了else, 觸發(fā)了throw new Error
其實(shí)看到這里我們就明白了, element在做prop判斷的時(shí)候, 是通過(guò)判斷key在不在model中的方式 來(lái)判斷path是否合法的, 那我們知道這個(gè)原理之后, 只需要將我們的代碼稍稍改動(dòng)一下即可。

我們只需要將tableData移到ruleForm中即可, 然后我們?cè)賮?lái)看控制臺(tái)已經(jīng)不報(bào)錯(cuò)了。

總結(jié)
我考慮了一下element為什么要這樣做,因?yàn)樵谶@樣的前提下,只看文檔 應(yīng)該不會(huì)得到有用的信息, 后來(lái)想了一會(huì)兒想通了, 因?yàn)閑lement要判斷prop傳遞的值是否合法的話, 就只能用 一個(gè)obj 一個(gè)key 通過(guò)key in obj 這樣的方式來(lái)判斷, 而如果我們不把tableData放到ruleForm中, form-item在mounted的時(shí)候 是拿不到外面this的data的, 所以他無(wú)法判斷 當(dāng)前傳進(jìn)來(lái)的tableData到底是誰(shuí), 也就沒(méi)有辦法使用key in obj.
到此這篇關(guān)于element中form組件prop嵌套屬性的問(wèn)題解決的文章就介紹到這了,更多相關(guān)element form組件prop嵌套內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
html+vue.js 實(shí)現(xiàn)漂亮分頁(yè)功能可兼容IE
功能比較簡(jiǎn)單,在單一html中使用vue.js分頁(yè)展示數(shù)據(jù),并未安裝腳手架,或使用相關(guān)UI框架,此時(shí)需要手寫(xiě)一個(gè)分頁(yè)器,不失為最合理最便捷的解決方案,需要的朋友可以參考下2020-11-11
Vue項(xiàng)目的表單校驗(yàn)實(shí)戰(zhàn)指南
這篇文章主要介紹了Vue項(xiàng)目表單校驗(yàn)的相關(guān)資料,前端表單校驗(yàn)?zāi)軠p少無(wú)效請(qǐng)求,保護(hù)后端接口,使用ElementPlus表單組件進(jìn)行校驗(yàn),需要準(zhǔn)備表單對(duì)象、規(guī)則對(duì)象并進(jìn)行雙向綁定,用戶名、密碼以及協(xié)議勾選等字段都需符合特定規(guī)則,需要的朋友可以參考下2024-10-10
vue3+Element?Plus?v-model實(shí)現(xiàn)父子組件數(shù)據(jù)同步的案例代碼
這篇文章主要介紹了vue3+Element?Plus?v-model實(shí)現(xiàn)父子組件數(shù)據(jù)同步,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
Vue3超詳細(xì)的ref()用法教程(看這一篇就夠了!)
這篇文章主要給大家介紹了關(guān)于Vue3超詳細(xì)的ref()用法的相關(guān)資料,在Vue3中ref函數(shù)不僅可以用于在組件中獲取DOM元素或子組件的引用,還可以直接訪問(wèn)組件元素本身,需要的朋友可以參考下2023-07-07
vue?動(dòng)態(tài)添加el-input的實(shí)現(xiàn)邏輯
這篇文章主要介紹了vue?動(dòng)態(tài)添加el-input的實(shí)現(xiàn)代碼,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
Vue使用自定義指令實(shí)現(xiàn)拖拽行為實(shí)例分析
這篇文章主要介紹了Vue使用自定義指令實(shí)現(xiàn)拖拽行為,結(jié)合實(shí)例形式分析了Vue使用自定義指令實(shí)現(xiàn)拖拽行為具體步驟、原理與操作注意事項(xiàng),需要的朋友可以參考下2020-06-06
vue webuploader 文件上傳組件開(kāi)發(fā)
本篇文章主要介紹了vue webuploader 文件上傳組件開(kāi)發(fā),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
vue3.0 CLI - 1 - npm 安裝與初始化的入門(mén)教程
這篇文章主要介紹了vue3.0 CLI - 1 - npm 安裝與初始化的入門(mén)教程,本文通過(guò)實(shí)例代碼相結(jié)合的形式,給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09

