父子组件之间的交互
- 子组件要求父组件传递的变量写在
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>
   |