在實際應用中,往往需要一個報表列表頁,支持表單數據的添加或修改,操作完畢后關閉子頁並刷新列表頁面,效果如下圖

主頁面關鍵代碼:
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: { // 關閉彈框,賦值父頁面。isRefresh用於標識是否刷新父頁面(子頁面內容有變化時傳入true值) 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>
