关于vue组件通信的一些总结

这次在做项目的时候又遇到了组件通信的问题,还是自己不太理解这其中的奥秘,平时用的也比较少。所以在开发中才会多次遇到问题,这次做个总结吧,希望对以后会有帮助!

需求是这样:一个tab切换的组件,需要在一个页面中调用两次,当改变其中一个的状态的时候另外一个也要跟着改变。

组件中的列表是通过父组件传递过来的。

最开始我的做法是这样:

step1:通过props获取父组件的值将tab列表渲染

step2:在computed中设置defaultId为列表第一项的id

step3:tab激活状态的条件是id == defaultId

代码大致长这样:

<template>
    <div>
        <span v-for="tab in tabs" 
            :key="tab.id" 
            :class="{active: defaultId == tab.id}
            @click="switchTab(tab.id)""></span>
    </div>
</template>


export default {
    props: {
        tabs: Array
    },
    computed: {
        defaultId () {
            return this.tabs[0].id
        }
    },
    methods: {
        switchTab (id) {
            this.defaultId = id
        }
    }
​​​​​​​}

这里存在两个错误:

1.要修改defaultId的值需要在computed中设置set,详见官网

2.defaultId的变化需要的是它的依赖发生变化,才会触发,也就是这里的tabs

尝试失败后,我又把computed改成了data。

<template>
    <div>
        <span v-for="tab in tabs" 
            :key="tab.id" 
            :class="{active: defaultId == tab.id}
            @click="switchTab(tab.id)""></span>
    </div>
</template>


export default {
    props: {
        tabs: Array
    },
    data () {
        defaultId: this.tabs[0].id
    },
    methods: {
        switchTab (id) {
            this.defaultId = id
        }
    }
​​​​​​​}

换成data后惊喜的发现,点击的组件状态是客户发生变化的,好开心啊!然后再仔细一看事情并不是那么简单,另外一个组件的状态居然没发生变化???不都是公用的defaultId吗?这是怎么回事?仔细回想了一番原来是这样。数据再data中使用函数的形式返回,就相当于这个数据只在这个组件中起作用,类似一个组件作用域,虽然这个组件在页面中复用了两次,但是每次都是一个独立的组件,互不干涉。

一番摸索还不成功,最后在同事的提醒下才恍然大悟,defaultId可以直接从父组件中传递,改变defaultId可以使用$emit $on触发。具体代码如下:

<template>
    <div>
        <span v-for="tab in tabs" 
            :key="tab.id" 
            :class="{active: defaultId == tab.id}
            @click="switchTab(tab.id)""></span>
    </div>
</template>


export default {
    props: {
        tabs: Array,
        defaultId: Number
    },
    methods: {
        switchTab (id) {
            this.$emit('switch-id', id)
        }
    }
​​​​​​​}

// 父组件

<template>
    <child :tabs='xxx' :defaultId="xxx" @switch-id="changeId"></child>
</template>


export default {
    props: {
        tabs: Array,
        defaultId: Number
    },
    methods: {
        changeId (data) {
            this.defaultId = data
        }
    }
​​​​​​​}

这样改变props中的defaultId就可以同时触发两个组件中的状态了。

 

总结:

1.不管组件通信中改变数据状态要从源头上改变(父组件),不要在父组件重尝试改变props的值。

2.要学会使用$emit $on

tips:

1.组件传参的时候如果父组件的传过来的值是接口返回的,这是子组件已经渲染了但是父组件还没有这个值,所以在子组件中就接收不到。这种情况下就在父组件加一个v-if判断,当有值时才渲染子组件。

2.$emit传参到父组件,父组件接收这个参数并且自己还要传参数的时候可以使用$event

// 父组件

<template>
    <child :tabs='xxx' :defaultId="xxx" @switch-id="changeId($event, 1)"></child>
</template>


export default {
    props: {
        tabs: Array,
        defaultId: Number
    },
    methods: {
        changeId (data, type) {
            this.defaultId = data
            console.log(type) // 1
        }
    }
​​​​​​​}

或者:这里(还没看太懂)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值