Vue 组件通讯方式

目录

props 和 $emit

$attrs($listeners)

provide/inject

$parent、$refs($children)

自定义事件

Vuex

总结


props 和 $emit

适合父子组件,父组件给子组件传递数据和函数,传函数时,子组件可返回数据给父组件

示例

// parent 里
<Child :list="list" @add="addHandler"></Child> // Vue 里传数据用:,传函数用@,内容用引号,且不加 this

// child 里
export default {
    props: { // Vue 里子组件用 props 获取父组件传来的数据
        list: { // 类型检查和默认值
            type: PropTypes.arrayof(PropTypes.object).isRequired,
            default() {
                return []
            }
        }
    },
    emits: ['add'], // vue3 新增要写的
    methods: {
        addInChild(){
            console.log(this.list) // 子组件下面直接从 this 里获取数据 
            this.$emit("add", this.title) // 用 $emit 调用父组件传来的函数
        }
    }
}


 

$attrs($listeners)

适合父子组件和上下级(跨多级)组件(不是很完美),props 和 emits 的后补,子组件没有在 props 和 emits 里接收的数据和函数,可以在 $attrs 和 $listeners 里获取到

Vue3 把 $listeners 合并到了 $attrs 里

v-bind="$attrs" 可把爷辈组件的 $attrs 数据透传给孙子组件,实现爷孙组件通讯,但依赖于 v-bind="$attrs",并不是很方便

inheritAttrs: false 可避免把 $attrs 的数据绑到 dom 节点上,注意正常只在有一个 dom 元素的时候才会绑定

示例

// level1
<Level2
    :a="a"
    :b="b"
    :c="c"
    @getA="getA"
    @getB="getB"
    @getC="getC"
></Level2>
data() {
    return {
        a: 'aaa',
        b: 'bbb',
        c: 'ccc'
    }
},
methods: {
    getA() {
        return this.a
    },
    getB() {
        return this.b
    },
    getC() {
        return this.c
    }
}

// level2
<Level3
    :x="x"
    :y="y"
    :z="z"
    @getX="getX"
    @getY="getY"
    @getZ="getZ"
    v-bind="$attrs" // 把爷辈组件的 $attrs 数据透传给孙子组件
></Level3>
props: ['a'],
emits: ['getA'],
data() {
    return {
        x: 'xxx',
        y: 'yyy',
        z: 'zzz'
    }
},
methods: {
    getX() {
        return this.x
    },
    getY() {
        return this.y
    },
    getZ() {
        return this.z
    }
},
created() {
    console.log(this.$attrs) // b、c、getB、getC
}

// level3
<p>level3</p>
props: ['x'],
emits: ['getX'],
inheritAttrs: false, // 避免把 $attrs 的数据绑到 dom 节点上
created() {
    console.log(this.$attrs) // b、c、getB、getC、y、z、getY、getZ
}

 

provide/inject

完美的上下级(跨多级)组件通讯方式,上级组件用 provide 提供数据,下级组件用 inject 接收数据

示例

// level1
import { computed } from 'vue'
<Level2></Level2>
provide: {
    info: 'aaa'
}
provide() { // 如果提供的是一个变量,需要这样写
    return {
        info: computed(() => this.name)
    }
}

// level2
<Level3></Level3>

// level3
<p>{{ info }}</p>
inject: ['info ']

$parent、$refs($children)

适合父子组件,用 this.$parent 可直接获取父组件,用 $refs 获取子组件

获取子组件,Vue2 里有 $children、Vue3 建议用 $refs,注意要在 mounted 里获取,不能在 created 里,因为 created 里组件还没渲染完成

示例

// level1
<Level2 ref='level2'></Level2>
mounted() { // 注意要在 mounted 里获取,不能在 created 里
    console.log(this.$refs.level2.x) // this.$refs 获取到子组件,然后获取其属性
}


// level2
mounted() {
    console.log(this.$parent.a) // this.$parent 获取到父组件,然后获取其属性
    this.$parent.getA() // this.$parent 获取到父组件,然后调用其方法
}

自定义事件

适合全局不相关组件通讯,以及多个组件触发多个组件响应的情况

示例

// Vue2 里实例已经实现了自定义事件 API
const event = new Vue()
// Vue3 里需要引入第三方自定义事件
import ee from 'event-emitter'
const event = new ee()


// 触发事件
event.$emit('onAddTitle', this.title)

// 绑定响应事件
event.$on('onAddTitle', this.addTitleHandler) // 使用 this.addTitle 函数名字而不是匿名函数是为了销毁组件时解绑

// 解绑,避免内存泄漏
beforeDestroy() { // Vue3 里改成了 beforeUnmount
    event.$off('onAddTitle', this.addTitleHandler)
}

Vuex

适合全局不相关组件共享数据

总结

最常用的是 props 和 $emit,用于父子组件数据传递,父组件用 props 传数据和函数给子组件,子组件调用函数可回传数据给父组件 ->

对于没有显式接收的 props,可用 $attrs 接收到,用 v-bind 可再传递给孙子组件,但用这种方式进行上下级组件传递不够完美,因为严重依赖 v-bind ->

provide/inject 是完美的跨级传递数据的方式,上级组件用 provide 提供数据,下级组件用 inject 接收数据 ->

父子组件传递还有一种 $parent、$refs 直接获取父子组件的方式 ->

对于全局无关联组件,可用自定义事件实现事件和数据通讯 ->

全局纯数据同步可用 Vuex 实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值