Vue?elementUI表單嵌套表格并對每行進行校驗詳解
效果展示
先看看這是不是需要的效果^_^

如圖,ElementUI 表單里嵌套了表格,表格內(nèi)每行能進行【保存】【新增】【編輯】【刪除】【重置】等操作,同時可以對每行的某些字段進行校驗(而不是整個表單校驗!),這種需求很常見,所以記錄下來。
代碼鏈接
關(guān)鍵代碼
表格數(shù)據(jù)
// 數(shù)據(jù)格式必須是【對象嵌套數(shù)組】,【form】綁定表單,【list】綁定表格
form: {
// 表格數(shù)據(jù)
list: [
{ id: 1, name: '小葉', age: '12', phone: '123456', show: true },
{ id: 2, name: '小李', age: '23', phone: '123457', show: true },
{ id: 3, name: '小林', age: '12', phone: '123458', show: true }
]
},
組件嵌套
- 添加字段校驗的時候,格式必須寫成這樣的 :prop="'list.' + scope.$index + '.name'"
這是 elementui 規(guī)定的格式,渲染后的結(jié)果為 list.1.name - 每個字段要動態(tài)綁定表單的 rules 屬性
- 如果不是以上的格式,會出錯?。。?/li>
// 表單必須嵌套在表格的外面,表單必須綁定【rules】【ref】屬性
<el-form :model="form" :rules="rules" ref="form">
<el-table :data="form.list">
<el-table-column prop="name" label="姓名">
<template scope="scope">
// 每個字段動態(tài)的綁定表單的【prop】【rules】屬性
<el-form-item :prop="'list.' + scope.$index + '.name'" :rules="rules.name">
<el-input size="mini" v-model="scope.row.name" placeholder="請輸入" clearable></el-input>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
校驗方法
- 表單的字段對象存在于 this.$refs['form'].fields 中,并且字段對象具有 prop【datas.1.name】 屬性和 validateField 方法【驗證 datas.1.name 能否通過校驗】
- 但是 validateField 方法需要手動創(chuàng)建來驗證能否通過校驗
- 必須創(chuàng)建,否則會出錯?。?!
// 表單校驗方法
// 【form】是需要校驗的表單,就是表單中【ref】綁定的字段
// 【index】是需要傳入的行數(shù),字段【scope.$index】
validateField(form, index) {
let result = true;
for (let item of this.$refs[form].fields) {
if(item.prop.split(".")[1] == index){
this.$refs[form].validateField(item.prop, err => {
if(err !="") {
result = false;
}
});
}
if(!result) break;
}
return result;
}
重置方法
// 對【需要校驗】的表單字段進行重置
// 參數(shù)同校驗方法,如果是全部重置
reset(form, index) {
this.$refs[form].fields.forEach(item => {
if(item.prop.split(".")[1] == index){
item.resetField();
}
})
}
// 如果需要全部重置可以直接質(zhì)控表單中字段
// 【row】是每行傳入的數(shù)據(jù)
resetRow(row) {
row.name = "";
row.age = "";
row.phone = "";
}
完整代碼
因為用的是在線鏈接,網(wǎng)絡(luò)不穩(wěn)定時頁面不一定能加載出來,使用時可以更換成本地的!
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue表單嵌套表格逐行驗證</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 引入樣式 -->
<link rel="stylesheet" rel="external nofollow" >
<!-- 引入組件庫 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="app">
<!-- 頁面組件 -->
<h2 style="text-align: center; line-height: 23px;color: #909399;">vue表單嵌套表格逐行驗證</h2>
<el-form :model="form" :rules="rules" ref="form" :inline="true"
style="margin: 23px auto 0px; width: 96%; overflow: hidden;">
<el-table border :data="form.list">
<el-table-column align="center" prop="id" label="序號" width="55">
</el-table-column>
<el-table-column align="center" prop="name" label="姓名">
<template scope="scope">
<el-form-item :prop="'list.' + scope.$index + '.name'" :rules="rules.name"
v-if="scope.row.show">
<el-input size="mini" v-model="scope.row.name" placeholder="請輸入" clearable>
</el-input>
</el-form-item>
<div v-if="!scope.row.show">{{scope.row.name}}</div>
</template>
</el-table-column>
<el-table-column align="center" prop="age" label="年齡">
<template scope="scope">
<el-form-item :prop="'list.' + scope.$index + '.age'" :rules="rules.age" v-if="scope.row.show">
<el-input size="mini" v-model="scope.row.age" placeholder="請輸入" clearable>
</el-input>
</el-form-item>
<div v-if="!scope.row.show">{{scope.row.age}}</div>
</template>
</el-table-column>
<el-table-column align="center" prop="phone" label="聯(lián)系方式">
<template scope="scope">
<el-form-item :prop="'list.' + scope.$index + '.phone'" :rules="rules.phone"
v-if="scope.row.show">
<!-- <el-form-item v-if="scope.row.show"> -->
<el-input size="mini" v-model="scope.row.phone" placeholder="請輸入" clearable>
</el-input>
</el-form-item>
<div v-if="!scope.row.show">{{scope.row.phone}}</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="290" fixed="right">
<template slot-scope="scope">
<el-button type="text" style="color: #E6A23C;" @click="save(scope.$index, scope.row)"
v-if="scope.row.show" icon="el-icon-check">保存
</el-button>
<el-button type="text" style="color: #409EFF;" @click="edit(scope.row)" v-if="!scope.row.show"
icon="el-icon-edit">編輯
</el-button>
<el-button type="text" style="color: #67C23A;" v-if="scope.$index+1 == listLength"
@click="addRow(scope.$index, scope.row)" icon="el-icon-plus">新增
</el-button>
<el-button type="text" style="color: #F56C6C;" @click="delRow(scope.$index, scope.row)"
icon="el-icon-delete">刪除
</el-button>
<el-button type="text" style="color: #909399;" @click="reset('form', scope.$index)"
v-if="scope.row.show" icon="el-icon-refresh">重置
</el-button>
<!-- <el-button type="text" style="color: #909399;" @click="resetRow(scope.row)"
v-if="scope.row.show" icon="el-icon-refresh">重置
</el-button> -->
</template>
</el-table-column>
</el-table>
</el-form>
</div>
</body>
</html>
<script>
var app = new Vue({
el: '#app',
data() {
return {
// 表單數(shù)據(jù)
form: {
// 表格數(shù)據(jù)
list: [{ id: 1, name: '', age: '', phone: '', show: true }]
},
// 表單驗證規(guī)則
rules: {
name: [{ required: true, message: '請輸入姓名!', trigger: 'blur' }],
age: [{ required: true, message: '請輸入年齡!', trigger: 'blur' }],
phone: [{ required: true, message: '請輸入聯(lián)系方式!', trigger: 'blur' }],
},
// 表格長度默認為 1
listLength: 1,
}
},
methods: {
// 校驗
validateField(form, index) {
let result = true;
for (let item of this.$refs[form].fields) {
if (item.prop.split(".")[1] == index) {
this.$refs[form].validateField(item.prop, err => {
if (err != "") {
result = false;
}
});
}
if (!result) break;
}
return result;
},
// 重置【只針對校驗字段】
reset(form, index) {
this.$refs[form].fields.forEach(item => {
if (item.prop.split(".")[1] == index) {
item.resetField();
}
})
},
// 重置【全部】
resetRow(row) {
row.name = "";
row.age = "";
row.phone = "";
},
// 保存
save(index, row) {
if (!this.validateField('form', index)) return;
row.show = false;
},
// 新增
addRow(index, row) {
if (!this.validateField('form', index)) return;
this.form.list.push({
id: index + 2,
name: '',
age: '',
phone: '',
show: true
});
this.listLength = this.form.list.length;
},
// 編輯
edit(row) {
row.show = true;
},
// 刪除
delRow(index, row) {
if (this.form.list.length > 1) {
this.form.list.splice(index, 1);
this.listLength = this.form.list.length;
} else {
this.form.list = [{
id: 1,
name: '',
age: '',
phone: '',
show: true
}];
}
},
}
})
</script>總結(jié)
到此這篇關(guān)于Vue elementUI表單嵌套表格并對每行進行校驗的文章就介紹到這了,更多相關(guān)elementUI表單嵌套表格內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3模塊創(chuàng)建runtime-dom源碼解析
這篇文章主要為大家介紹了vue3模塊創(chuàng)建runtime-dom源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01
詳解Vue的Pinia如何做到刷新不丟數(shù)據(jù)
Pinia 是 Vue 3 的官方推薦狀態(tài)管理庫,旨在替代 Vuex,提供更簡單、直觀的狀態(tài)管理解決方案,Pinia 的設(shè)計理念是簡單、易于學習和使用,本文給大家詳細介紹了Vue的Pinia如何做到刷新不丟數(shù)據(jù),需要的朋友可以參考下2025-01-01
vue-cli3項目生產(chǎn)和測試環(huán)境分包后文件名和數(shù)量不一致解決
這篇文章主要為大家介紹了vue-cli3項目生產(chǎn)和測試環(huán)境分包后文件名和數(shù)量不一致解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
vite+vue3搭建的工程實現(xiàn)批量導(dǎo)入store的module
這篇文章主要介紹了vite+vue3搭建的工程實現(xiàn)批量導(dǎo)入store的module方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
Vue.extend和VueComponent的關(guān)系源碼解析
這篇文章主要為大家詳解了Vue.extend和VueComponent的關(guān)系源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02

