父子组件之间的交互
- 子组件要求父组件传递的变量写在
props中
- 子组件自己维护的,不需要父组件传递的变量写在
data中
- 在子组件内调用父组件方法:子组件用
$emit发起一个事件(可以带事件参数),父组件用v-on或@监听这个事件并做处理(监听方法的形参就是子组件传的参数)
- 父组件调用子组件方法:父组件在子组件上定义
ref属性, 父组件用this.$refs.refName.method去调用子组件方法。
示例:分页表格组件
TablePage功能:
- 翻页时、改变页大小时,自动调用后台查找
- 固定一列操作列,数据列和操作列分开从父组件传
- 当操作列中的按钮大于1时,这些按钮应折叠在“更多”下拉按钮中,如“编辑”、“删除”。如果不需要这些操作,操作列应该隐藏
框架是iView。设置好跨域访问和axios全局后,使用<Table />和<Page />以及slot-scope实现以上功能。
TablePage组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| <template> <div> <Table :columns="insideColumns" :data="data" border> <template slot-scope="{ row, index }" slot="action">
<template v-if="actionNumber < 2"> <a @click="firstAction.onClick(row)">{{firstAction.name}}</a> </template>
<template v-else> <Dropdown transfer trigger="click"> <a href="javascript:void(0)">More<Icon type="ios-arrow-down"></Icon></a> <DropdownMenu slot="list"> <DropdownItem v-for="(item, index) in insideActions" :key="index" > <a @click="item.onClick(row)">{{item.name}}</a> </DropdownItem> </DropdownMenu> </Dropdown> </template>
</template> </Table> <div style="margin-top: 10px"> <Page transfer :current="currentPage" :total="count" :page-size="pageSize" show-elevator show-total show-sizer @on-change="changePage" @on-page-size-change="changePageSize" /> </div> </div> </template>
<script> export default { name: 'TablePage', props: { data: { type: Array, default () { return []; } }, columns: { type: Array, default () { return []; } }, actions: { type: Array, default () { return []; } }, count: { type: Number, default: 0 }, currentPage: { type: Number, default: 1 }, pageSize: { type: Number, default: 10 } }, data () { return { insideColumns: [], actionNumber: 0, firstAction: {}, insideActions: [], }; }, methods: { changePage (newPage) { this.currentPage = newPage; this.getData(); }, changePageSize (newPageSize) { this.pageSize = newPageSize; this.getData(); }, getData () { this.$emit('get-data', this.currentPage, this.pageSize); }, handleColumns (columns) { let actionColumn = { title: 'Action', slot: 'action', width: 130, fixed: 'right', resizable: true }; if (this.actions && this.actions.length > 0) { this.insideColumns = columns.concat(actionColumn); } }, handleActions (actions) { this.actionNumber = actions.length; if (this.actionNumber > 0) { this.firstAction = actions[0]; if(this.actionNumber > 1) { let more = [...actions]; this.insideActions = more; } } } }, mounted () { this.handleColumns(this.columns); this.handleActions(this.actions); } }; </script>
|
上面代码中的getData()方法很关键,它是TablePage与父组件通信的桥梁,通过this.$emit()触发名为”get-data”的事件,并传递参数currentPage和pageSize。在父组件中,需要v-on这个事件,得到这两个参数。
父组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| <template> <div> <div style="margin-bottom: 10px"> <Button @click="search()">查询</Button> </div> <TablePage :columns="columns" :data="data" :count="count" :currentPage="currentPage" :pageSize="pageSize" @get-data="loadData" <!--子组件内$emit的事件--> :actions="actions" > </TablePage>
</div> </template>
<script> import TablePage from './table-page'
export default { name: 'PersonManage', components: { TablePage }, data () { return { currentPage: 1, pageSize: 10, count: 0, columns: [ { title: 'ID', key: 'id' }, { title: 'Lastname', key: 'lastname' }, { title: 'Firstname', key: 'firstname' }, { title: 'City', key: 'city' }, { title: 'Address', key: 'address' } ], data: [], actions: [ { name: 'Edit', onClick: (row) => this.handleEdit(row) }, { name: 'Delete', onClick: (row) => this.handleDelete(row.id)} ], } }, methods: { search(){ this.currentPage = 1 this.loadData(this.currentPage, this.pageSize) }, loadData(currentPage, pageSize){ this.currentPage = currentPage this.pageSize = pageSize
this.$axios({ url: '/man/person/getListByPage', method: 'post', data: { currentPage: this.currentPage, pageSize: this.pageSize } }).then(res => { let resData = res.data let pageData = resData.data this.data = pageData.dataList this.count = pageData.count }); }, handleEdit(row){ console.log('edit=====>'+JSON.stringify(row)) }, handleDelete(rowId){ console.log('delete=====>'+JSON.stringify(rowId)) }, } } </script>
|
currentPage和pageSize由父组件传入子组件,而不是由子组件维护,原因是:父组件在改变currentPage和pageSize的值后应该同步到子组件,这样子组件的<Page />组件才能与实际页码和页大小匹配。
父组件改变currentPage和pageSize的场景:点击查询按钮时,需要把当前页码currentPage改为1。
因此,这两个参数也应该由父组件传入子组件,子组件改变它的值后通知到父组件。
父组件调用子组件方法例子
抄自:https://www.cnblogs.com/renzm0318/p/8762129.html
子组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <template> <div> childComponent </div> </template>
<script> export default { name: "child", methods: { childClick(e) { console.log(e) } } } </script>
|
父组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <template> <div> <button @click="parentClick">点击</button> <Child ref="mychild" /> </div> </template>
<script> import Child from './child'; export default { name: "parent", components: { Child }, methods: { parentClick() { this.$refs.mychild.childClick("子组件方法"); } } } </script>
|