element中form組件prop嵌套屬性的問題解決
Introduction
分享今天同事問的一個問題, 下面這段代碼會報錯,先看代碼:重點是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: "請輸入活動名稱",
trigger: "blur",
validator(rule, value, callback) {
console.log("rule: ", rule);
console.log("value: ", value);
},
},
],
},
};
},
};
</script>我第一眼看上去的時候并沒有發(fā)現(xiàn)什么問題,但這段代碼實實在在的報錯了,我們來看一下錯誤

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

2. 我們根據(jù)他的報錯來分析, 首先他說`mounted hook`中報錯, 那我們就直接來看這個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定義一個initialValue屬性
Object.defineProperty(this, 'initialValue', {
value: initialValue
});
this.addValidateEvents();
}
}我看這段代碼的第一反應是, 這也沒干什么事兒啊, 就取了個值 賦了個值, 看了一會兒我發(fā)現(xiàn), 有一個盲點就是this.fieldValue這里, 這是一個什么東西呢?不知道 去看一下。
computed: {
fieldValue() {
// 1.拿到當前"form"的model屬性(這里很重要, 要記住這一步)
const model = this.form.model;
if (!model || !this.prop) { return; }
// 2.拿到當前"form-item"的prop屬性,
// 也就是我們傳的那個: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)這是一個computed屬性(步驟見注釋), 發(fā)現(xiàn)最終返回getPropByPath方法的返回結果, 我們接著去看一下這個方法.
我們發(fā)現(xiàn)這個方法是在utils/util下的一個方法

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

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

我們只需要將tableData移到ruleForm中即可, 然后我們再來看控制臺已經(jīng)不報錯了。

總結
我考慮了一下element為什么要這樣做,因為在這樣的前提下,只看文檔 應該不會得到有用的信息, 后來想了一會兒想通了, 因為element要判斷prop傳遞的值是否合法的話, 就只能用 一個obj 一個key 通過key in obj 這樣的方式來判斷, 而如果我們不把tableData放到ruleForm中, form-item在mounted的時候 是拿不到外面this的data的, 所以他無法判斷 當前傳進來的tableData到底是誰, 也就沒有辦法使用key in obj.
到此這篇關于element中form組件prop嵌套屬性的問題解決的文章就介紹到這了,更多相關element form組件prop嵌套內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
仿ElementUI實現(xiàn)一個Form表單的實現(xiàn)代碼
這篇文章主要介紹了仿ElementUI實現(xiàn)一個Form表單的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04
vue el-table字段點擊出現(xiàn)el-input輸入框,失焦保存方式
這篇文章主要介紹了vue el-table字段點擊出現(xiàn)el-input輸入框,失焦保存方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02
ElementUI日期選擇器時間選擇范圍限制的實現(xiàn)
在日常開發(fā)中,我們會遇到一些情況,限制日期的范圍的選擇,本文就詳細的介紹了ElementUI日期選擇器時間選擇范圍限制的實現(xiàn),文中通過示例代碼介紹的非常詳細,感興趣的可以了解一下2022-04-04
vue項目打包解決靜態(tài)資源無法加載和路由加載無效(404)問題
這篇文章主要介紹了vue項目打包,解決靜態(tài)資源無法加載和路由加載無效(404)問題,靜態(tài)資源無法使用,那就說明項目打包后,圖片和其他靜態(tài)資源文件相對路徑不對,本文給大家介紹的非常詳細,需要的朋友跟隨小編一起看看吧2023-10-10
Vue計算屬性與監(jiān)視屬性實現(xiàn)方法詳解
最近在學習vue,學習中遇到了一些感覺挺重要的知識點,感覺有必要整理下來,這篇文章主要給大家介紹了關于Vue.js中計算屬性、監(jiān)視屬性的相關資料,需要的朋友可以參考下2022-08-08

