VUE項目中,組件嵌套使用的時候,常常須要用到互相傳值,用到的方法不怪乎如下兩種:vue
<template> <div> <Child :myProp="data"></Child> </div> </template> <script> import Child from "@/Child"; export default { components: { Child }, data() { return { data: "123321" } } }; </script>
子組件:vuex
<template> <div> <h1>{{myProp}}</h1> </div> </template> <script> export default { data() { return {}; }, props:{ myProp:{ type:String, default:"" } }, }; </script>
2.子組件經過 $emit方法發送子組件內部的數據給父組件,將須要傳的值做爲$emit的第二個參數,該值將做爲實參傳給響應自定義事件的方法api
父組件:this
<template> <div> <Child @handle="myHandle"></Child> </div> </template> <script> import Child from "@/Child"; export default { components: { Child }, data() { return { } }, method:{ myHandle(str){ console.log(str);// => 123321 } } }; </script>
子組件:spa
<template> <div> <h1>1112222</h1> <button @click='onclick'></button> </div> </template> <script> export default { data() { return {}; }, method:{ onclick(){ this.$emit('handle','123321') } } }; </script>
3.另外,兄弟組件直接傳值則是經過bus,說白了就是new Vue(),因爲Vue 沒有直接子對子傳參的方法,建議將須要傳遞數據的子組件,都合併爲一個組件。若是必定須要子對子傳參,能夠先從傳到父組件,再傳到子組件。或者經過eventBus或vuex(小項目少頁面用eventBus,大項目多頁面使用 vuex)傳值。code
4.以及.sync
也只是上面幾種方法的語法糖。component
可是我在實際開發過程當中,遇到一個比較特殊的場景需求,父組件請求接口,拿到的初始數據發給子組件,在子組件內修改表單後,在父組件執行提交操做,並且,子組件是經過Tab的切換的,還使用keep-live包裹, component 是使用v-bind:is
切換orm
通過屢次嘗試,和探索,發現一種不錯的解決方案,接口
父組件:事件
<template> <el-tabs v-model="currentTab" :before-leave="tabBeforeLeave"> <el-tab-pane v-for="(tab, $index) in tabs" :key="$index" :name="tab.alias"> <span slot="label"> {{tab.name}} </span> <transition> <keep-alive > <component v-bind:is="tab.relationComponent" :ref="tab.relationComponent" :data="data" ></component> </keep-alive> </transition> </el-tab-pane> </el-tabs> </template> <script> import aComponent from "@/aComponent"; import bComponent from "@/bComponent"; import cComponent from "@/cComponent"; export default { components: { aComponent, bComponent, cComponent }, data() { return { tabs:[ { name: 'AAA', alias: 'aaa', relationComponent: 'aComponent', },{ name: 'BBB', alias: 'bbb', relationComponent: 'bComponent', },{ name: 'CCC', alias: 'ccc', relationComponent: 'cComponent', },], data:{ aChildData:{}, bChildData:{}, cChildData:{} } } }, created() { this.getData() }, method:{ getData(){ //接口請求以前保存的數據 this.$api.funy({ id: '123457' }, response => { if(response){ this.data.aChildData=response; this.currentTab = 'aaa'; this.$refs['aComponent'][0].localAssign(); } }, fal => { } ); }, submit(){ //組件內修改的數據,能夠經過下面這個方法獲取到,而且在父組件提交 let achild = this.$refs['aComponent'][0].sogalocal } } }; </script>
子組件aComponent:
<template> <div> <el-form v-model="sogalocal" label-width="120px"> <el-input type="textarea" :autosize="{ minRows: 4, maxRows: 6}" placeholder="placeholder" maxlength="42" show-word-limit v-model="sogalocal.desc"> </el-input> <el-radio-group v-model="sogalocal.bingAuth"> <el-radio label="jia">宋兵甲</el-radio> <el-radio label="yi">宋兵乙</el-radio> <el-radio label="bing">宋兵丙</el-radio> </el-radio-group> </el-form> </div> </template> <script> export default { name: 'child' props: { data:{ type: Object, default: () => {}, } }, data() { return { sogalocal: null }; }, created() {}, mounted(){}, methods: { localAssign(){ //等到父組件拿到數據,而後調用this.$refs['aComponent'][0].localAssign();實現數據本地化, //或者經過這個接口把數據傳過來localAssign(aChildData) this.sogalocal = Object.assign({},this.data.aChildData) }, } }; </script>