Vue 组件复杂表格高级编辑功能
在 vue 中组件的定义是希望组件可以做单一的功能,做到高复用,低耦合,所以父子组件之间的通信就比较关键,而在 vue 中 父组件传递给子组件的数据,子组件可以通过 props
接收,而 props
中的属性是不允许更改的,避免子组件直接操作父组件的数据。
而有时候我们又需要变更子组件绑定的数据,让父组件中绑定的数据同步更新,这个时候,我们就需要做一些特殊的处理,比如:
- 当功能比较简单时,我们可以使用
sync
修饰符来更新父组件的数据,比如el-dialog
1 组件的显示与隐藏,就是通过sync
来触发同步更新的。 - 当功能比较复杂的时候,我们可以使用
$emit('update:data', data)
的方法和函数绑定的方式,来通知父组件更新数据。
简单的父子组件之间实时数据更新,可以采用 $emit('update:data', data)
2 的方式。
1. 使用修饰符 sync 来同步更新父子组件中的绑定的数据
简单的父子组件之间的数据更新。
// 父组件
export default {
data() {
message: '父组件的消息!'
}
}
将父组件中的 message 传递给子组件 child-component 中。
<!-- 父组件 -->
<child-component :message.sync="message"></child-component>
子组件中接收父组件从传递过来的消息。
<!-- child-component.vue -->
<div>{{ message }}</div>
<button @click="setMessage">点击</button>
在子组件中更新父组件中的数据并在子组件中显现。
// child-component.vue
export default {
props: {
message: { type: String, default: '' }
},
data() {
return {}
},
methods: {
setMessage() {
this.$emit('update:meessage', '这是新的消息!')
}
}
}
当功能比较复杂时,需要结合一些场景进行特殊的处理,如下面的 【在 el-table
中 开发高级编辑表格功能】。
2. 在 el-table3 中开发高级编辑表格功能
高级编辑表格功能:
- 单元格可以编辑至少两种类型的数据,如 文本输入框、下拉选择框等。
- 单元格在切换数据源的同时赋予单元格以默认值。
- 在表格数据提交时,验证每个单元格的数据是否合法。
<el-table :data="tableData" border>
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column label="备注">
<template slot-scoped="{ row, $index }">
<child-component
v-if="row.is_edit"
:data="row"
@update:data="handleUpdate($event, index)"
></child-component>
<!-- 普通文本 -->
<div v-else>{{ item.cellName }}</div>
</template>
</el-table-column>
</el-table>
export default {
data() {
return {
tableData: [
{ id: 1, cellType: 1, cellName: 'ZHANGSAN', cellId: -1 },
{ id: 2, cellType: 2, cellName: '张三', cellId: 1 },
{ id: 3, cellType: 3, cellName: 'zhangsan@example.com', cellId: 1 }
],
userList: [
{ userId: 1, username: '张三' },
{ userId: 2, username: '李四' }
],
emailList: [
{ emailId: 1, email: '张三' },
{ emailId: 2, email: '李四' }
]
}
},
methods: {
handleUpdate(update, index) {
this.tableData[index].cellType = update.cellType
this.tableData[index].cellId = update.cellId
this.tableData[index].cellName = update.cellName
}
}
}
<template>
<div>
<!-- 类型1:输入框 -->
<el-input v-show="row.cellType === 1" v-model="row.cellName" @input="handleChange"></el-input>
<!-- 类型2:选择框 -->
<el-select v-show="row.cellType === 2" v-model="row.cellId" @change="handleChangeUser">
<el-option v-for="(item, index) in userList" :value="item.userId" :label="item.username">
</el-select>
<!-- 类型3:选择框 -->
<el-select v-show="row.cellType === 3" v-model="row.cellId" @change="handleChangeEmail">
<el-option v-for="(item, index) in emailList" :value="item.emailId" :label="item.email">
</el-select>
<el-popover trigger="hover">
<el-radio-group v-model="row.cellType" @change="handleRadio">
<el-radio :label="1">其他</el-radio>
<el-radio :label="2">用户</el-radio>
<el-radio :label="3">邮箱</el-radio>
</el-radio-group>
<el-button slot="reference" type="text" icon="el-icon-more"></el-button>
</el-popover>
</div>
</template>
export default {
props: {
data: { type: Object, default: () => { return {} } },
userList: { type: Array, default: () => [] },
emailList: { type: Array, default: () => [] }
},
data() {
return {
row: {
cellType: 1,
cellName: '',
cellId: -1
}
}
},
methods: {
handleChange(value) {
this.$emit('update:data', this.row)
},
handleChangeUser(value) {
this.row.cellName = this.userList.find(v => v.userId === value).username
this.$emit('update:data', this.row)
}
handleChangeEmail(value) {
this.row.cellName = this.emailList.find(v => v.emailId === value).email
this.$emit('update:data', this.row)
},
handleRadio() {
this.row.cellName = ''
this.row.cellId = -1
this.$emit('update:data', this.row)
}
}
}