4

VUE项目中,组件嵌套使用的时候,经常需要用到互相传值,用到的方法不怪乎以下两种:

  1. 父组件通过属性的方式给子组件传值,子组件用props进行数据的接收,父组件:
<template>
    <div>
        <Child :myProp="data"></Child>
    </div>
</template>
<script>
import Child from "@/Child";
export default {
 components: {
    Child
  },
  data() {
    return {
      data: "123321"
    }
  }
};
</script>

子组件:

<template>
    <div>
        <h1>{{myProp}}</h1>
    </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props:{
        myProp:{
          type:String,
          default:""
        }
    },
};
</script>

2.子组件通过 $emit方法发送子组件内部的数据给父组件,将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法

父组件:

<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>

子组件:

<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)传值。

4.以及.sync也只是上面几种方法的语法糖。

但是我在实际开发过程中,遇到一个比较特殊的场景需求,父组件请求接口,拿到的初始数据发给子组件,在子组件内修改表单后,在父组件执行提交操作,而且,子组件是通过Tab的切换的,还使用keep-live包裹, component 是使用v-bind:is切换

经过多次尝试,和探索,发现一种不错的解决方案,

父组件:

<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>

moonla
84 声望0 粉丝