在实际应用中,往往需要一个报表列表页,支持表单数据的添加或修改,操作完毕后关闭子页并刷新列表页面,效果如下图
主页面代码关键代码:
1)在主页面引入待弹出modal页的组件
<productEditModal
:show="{'showModal': showModal, 'productId': productId}"
@on-close="closeModal"
></productEditModal>
<script>
import productEditModal from '@/content/productEdit'// 数据源列表
export default {
components: {
productEditModal
},
...
</script>
2)在主页面中定义弹窗和关闭弹出的函数,其中,showModal、productId为定义的变量,将会传入弹出子页,分别代表是否弹出页和传入到子页面主键值
methods: {
// 关闭弹框,赋值父页面
closeModal (resVal) {
console.log('子组件传来的值:' + resVal)
this.showModal = resVal.isClose
if (resVal.isRefresh) {
this.getList()
}
},
// 弹出页面
openModal (index) {
console.log('序列号:' + index)
this.showModal = true
this.productId = 0// 默认新增0
index > -1 && (this.productId = this.tbData[index].id)
},
...
}
子页面代码关键代码:
1)定义modal页面内容
<template>
<Modal
v-model="showModal"
title="产品编辑"
width="800"
:footer-hide=true
:closable="false"
>
<!--此处放置表单中的控件-->
</Modal>
</template>
2)子页面在watch中接收父页面传来值并调用子页数据加载方法
export default {
// 父组件传来的值
props: ['show', 'productId'],
data () {
// 这里存放数据
return {
showModal: false,
curProduct: { id: 0, name: '', code: '', remark: '' }// 当前页面的产品信息
}
},
// 监听属性 类似于data概念
computed: {},
// 方法集合
methods: {
// 关闭子页面
onCancel (isRefresh) {
this.showModal = false
this.curProduct = { id: 0, name: '', code: '', remark: '' }// 初始化
this.$emit('on-close', { isclose: true, isRefresh: isRefresh })
},
...
init(productId){//缺省}
},
// 获取父页面传来的值,并根据主键id请求数据
watch: {
show (validate) {
console.log(validate)
if (validate.showModal === true) {
this.showModal = validate.showModal
if (validate.productId > 0) {
this.init(validate.productId)
} else {
this.curProduct = { id: 0, name: '', code: '', remark: '' }// 初始化
}
}
}
}
3)子页面重写保存和关闭按钮,隐藏modal的底部按钮区(:footer-hide=true),自行控制弹出页面的开关,请查看子页完整代码。
主页完整代码如下:


<template>
<div class="main-content">
<Row type="flex">
<i-col
span="2"
class="main-lable"
>
产品名称:
</i-col>
<i-col span="6">
<i-input
placeholder="请输入产品名称"
style="width: 200px"
v-model="proName"
></i-input>
</i-col>
<i-col span="8">
<Button
type="info"
icon="ios-search"
@click="getList"
>查询</Button>
<Button
icon="ios-add"
type="success"
@click="openModal(-1)"
>新增</Button>
</i-col>
</Row>
<div style="margin-top:10px">
<Table
border
:columns="tbColumns"
:data="tbData"
>
<template
slot-scope="{ row, index }"
slot="action"
>
<Button
type="error"
size="small"
style="margin-right: 5px"
@click="deleteRow(index)"
>删除</Button>
<Button
type="info"
size="small"
style="margin-right: 5px"
@click="openModal(index)"
>编辑</Button>
</template>
</Table>
</div>
<div class="main-page">
<Page
:total="totals"
:page-size="pageSize"
@on-change="change"
show-elevator
></Page>
</div>
<productEditModal
:show="{'showModal': showModal, 'productId': productId}"
@on-close="closeModal"
></productEditModal>
</div>
</template>
<script>
import productEditModal from '@/content/productEdit'// 数据源列表
export default {
data () {
return {
self: this,
proName: '', // 产品名称(过滤项)
totals: 0, // 数据行数
pageSize: 10, // 每页显示条数
pageIndex: 1, // 当前页
tbColumns:
[
{
title: '编号',
width: 80,
key: 'id'
},
{
title: '产品名称',
width: 150,
key: 'name'
},
{
title: '产品代码',
width: 100,
key: 'code'
},
{
title: '产品描述',
key: 'remark'
},
{
title: '操作',
slot: 'action',
width: 200,
align: 'center'
}
],
tbData: [],
showModal: false, // 是否显示子组件
productId: 0// 传给子组件的主键id
}
},
components: {
productEditModal
},
methods: {
// 关闭弹框,赋值父页面
closeModal (resVal) {
console.log('子组件传来的值:' + resVal)
this.showModal = resVal.isClose
if (resVal.isRefresh) {
this.getList()
}
},
// 弹出页面
openModal (index) {
console.log('序列号:' + index)
this.showModal = true
this.productId = 0// 默认新增0
index > -1 && (this.productId = this.tbData[index].id)
},
// 删除一条数据
deleteRow (index) {
var that = this
let proId = this.tbData[index].id
if (proId > 0) {
this.$Modal.confirm({
title: '提示',
content: '确认要删除名称为[' + this.tbData[index].name + ']的产品吗?',
onOk: () => {
this.$axios
.delete('/api/v1/product/' + proId)
.then(response => {
console.log(response)
debugger
if (response.data.isError) {
console.log(response)
this.$Modal.error({
title: '提示',
content: '删除失败!',
onOk: () => {
// this.$Message.info('Clicked ok')
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
// this.$Message.error('新增失败:' + response.data.message)
} else {
this.$Modal.success({
title: '提示',
content: '删除成功!',
onOk: () => {
// this.$Message.info('Clicked ok')
// this.onCancel(true)
debugger
that.getList()
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
}
})
.catch(function (error) { // 请求失败处理
console.log(error)
})
},
onCancel: () => {
this.$Message.info('您已取消删除.')
}
})
}
},
// 加载表格内容(含过滤、分页)
getList () {
// 拼装请求数据
let filter = {}
this.proName && (filter.name = { like: this.proName })
this.$axios
.post('/api/v1/product/list', { filter: filter, sort: { id: 'ASC', name: 'DESC' }, page: this.pageIndex, limit: this.pageSize })
.then(response => {
console.log(response)
this.tbData = response.data.data.docs
this.totals = response.data.data.totals
// console.log(this.totals)
})
.catch(function (error) { // 请求失败处理
console.log(error)
})
},
// 分页改变时
change (page) {
// console.log(page)
this.pageIndex = page
this.getList()
}
},
// 生命周期 - 挂载完成,template模板挂在到组件上(可以访问DOM元素)
mounted () {
this.getList()
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.main-content {
height: 100%;
}
.main-lable {
line-height: 30px;
text-align: right;
}
.main-page {
width: 100%;
position: absolute;
bottom: 2px;
text-align: center;
}
</style>
子页完整代码如下:productEdit.vue


<template>
<Modal
v-model="showModal"
title="产品编辑"
width="800"
:footer-hide=true
:closable="false"
>
<i-form :label-width="100">
<div class="ivu-card ivu-card-dis-hover">
<div
class="ivu-card-body"
style="verflow-y:auto;overflow-x: hidden;"
>
<div
class="ivu-row"
style="margin-left: -12px; margin-right: -12px;"
>
<Row type="flex">
<i-col span="12">
<Form-item
label="产品名称:"
prop="name"
>
<i-input
v-model="curProduct.name"
placeholder="请输入产品名称"
style="width:80%"
></i-input>
</Form-item>
</i-col>
<i-col span="12">
<Form-item
label="产品代码:"
prop="code"
>
<i-input
v-model="curProduct.code"
placeholder="请输入产品代码"
style="width:80%"
></i-input>
</Form-item>
</i-col>
</Row>
<Row type="flex">
<i-col span="24">
<Form-item label="数据源描述:">
<Input
type="textarea"
:rows="4"
placeholder="请输入数据源描述"
v-model="curProduct.remark"
style="width:91%"
/>
</Form-item>
</i-col>
</Row>
<div style="text-align: right;margin-top: 10px;">
<!-- <Button @click="onCancel()">取消</Button> -->
<button
type="button"
class="ivu-btn ivu-btn-primary"
@click="onSave"
>
<span>提交</span>
</button>
<button
type="button"
class="ivu-ml ivu-btn ivu-btn-default"
@click="onCancel(false)"
>
<span>取消</span>
</button>
</div>
</div>
</div>
</div>
</i-form>
</Modal>
</template>
<script>
// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
// 例如:import 《组件名称》 from '《组件路径》';
export default {
// 父组件传来的值
props: ['show', 'productId'],
data () {
// 这里存放数据
return {
showModal: false,
curProduct: { id: 0, name: '', code: '', remark: '' }// 当前页面的产品信息
}
},
// 监听属性 类似于data概念
computed: {},
// 方法集合
methods: {
// 关闭子页面
onCancel (isRefresh) {
this.showModal = false
this.curProduct = { id: 0, name: '', code: '', remark: '' }// 初始化
this.$emit('on-close', { isclose: true, isRefresh: isRefresh })
},
// 保存产品信息
onSave () {
console.log(this.isNew)
if (this.curProduct.id > 0) {
this.$axios
.put('/api/v1/product', { entity: this.curProduct })
.then(response => {
if (response.data.isError) {
this.$Modal.error({
title: '提示',
content: '修改失败',
onOk: () => {
// this.$Message.info('Clicked ok')
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
} else {
this.$Modal.success({
title: '提示',
content: '修改成功!',
onOk: () => {
this.onCancel(true)
// this.$Message.info('Clicked ok')
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
}
})
.catch(function (error) {
// 请求失败处理
console.log(error)
})
} else {
this.$axios
.post('/api/v1/product', { entity: this.curProduct })
.then(response => {
if (response.data.isError) {
console.log(response)
this.$Modal.error({
title: '提示',
content: '保存失败',
onOk: () => {
// this.$Message.info('Clicked ok')
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
// this.$Message.error('新增失败:' + response.data.message)
} else {
this.$Modal.success({
title: '提示',
content: '保存成功!',
onOk: () => {
// this.$Message.info('Clicked ok')
this.onCancel(true)
},
onCancel: () => {
// this.$Message.info('Clicked cancel')
}
})
}
})
.catch(function (error) {
// 请求失败处理
console.log(error)
})
}
},
init: function (proId) { // 初始化页面内容
console.log('子页初始化:' + proId)
// 编辑时
if (proId > 0) {
// 根据proId获得数据源信息,并加载到页面上
this.$axios
.get('/api/v1/product/' + proId)
.then(response => {
// console.log(response);
(response.data.data) && (this.curProduct = response.data.data)
console.log(this.curProduct)
})
.catch(function (error) { // 请求失败处理
console.log(error)
})
}
}
},
// 获取父页面传来的值,并根据主键id请求数据
watch: {
show (validate) {
console.log(validate)
if (validate.showModal === true) {
this.showModal = validate.showModal
if (validate.productId > 0) {
this.init(validate.productId)
} else {
this.curProduct = { id: 0, name: '', code: '', remark: '' }// 初始化
}
}
}
}
}
</script>
参考链接:https://blog.csdn.net/lemisi/article/details/89176251
来源:oschina
链接:https://my.oschina.net/u/4408223/blog/3421235