VUE3中的组件传值

731 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

现阶段vue3已经成了默认版本,那么vue3的学习也该赶上日程,今天刚学习了vue3组件中的传值,和vue2还是有一些不同的

父传子

父组件给子组件传值个人认为最好用的就是props,vue2与vue3这个种方式传值没有啥变化

父组件传值首先要在父组件中传出去

父组件中,别忘记在data中定义flag
<father :flag="flag"></father>
<script>
export default {
    data(){
        return {
            flag:"scc"
        }
    }
}
</script>
子组件
<template>
    <div>{{flag}}</div>
</template>
<script>
export default {
    props:['flag']
}
</script>

这样就会发现flag已经传递给了父组件

但是当我们给父组件一些我们常用的属性(例如class,id)能否传递给子组件呢,答案是不可以的,但是我们还是可以拿到的,

通过$attrs可以拿到所有没有被props接收的属性

我们在父组件中定义一个class属性

attrsFuther.png

子组件中没有用props接收

attrsSon.png

浏览器中展示效果

浏览器.png

所以我们是可以通过$attrs拿到没有被子组件接收的属性

这些props没有接收的属性,称为非props的attribute

如果属性没有被接收,并且子组件只有一个根元素,那么子组件的根元素会继承这个属性

可以看到我们并没有给这个div添加class属性,但是他却多了一个class 继承.png 如果不想继承,可以给子组件设置inheritAttrs:false

<template>
    <div>{{$attrs.class}}</div>
</template>

<script>
export default {
    inheritAttrs:false
}
</script>

我们看一下浏览器显示

继承2.png

可以看到上次继承的class属性消失了

子传父

子传父,用到emits属性,该属性可以设置为数组,或者对象,一般对象用来传参验证

emits:{
    add:payload=>{
        if(payliad>10)return true 
        return false
    }
}
激活
send(){
    this.$emit("add",参数)
}

注意函数必须要返回false或者true,返回false浏览器会警告,payload是参数 这样的话我们就注册了一个add的事件

我们在父组件中定义一个监听函数(注意监听的对象是这个组件,所以要写到这个组件上面)

 <Son @add="addone"/>

并且指定add事件被激活的回调函数addone

当send事件被触发,会触发add事件,父组件监听add事件,被触发调用addone方法

这样我们就完成了子传父

父传后代

这个有个provide/inject方法一般很少用,稍微说一下

父组件配置provide,所有的下级组件都可以通过inject访问的到

父组件

最好写成函数式,不然this会指向undefind,不方便
provide(){
    name:"scc"

}

子组件

inject:["name"]

非常需要注意的是,provide中的值不是双向绑定的,也就是说name发生变化,并不会引起页面的刷新 解决方法也很简单,vue3准备了computed方法

import {computed} from "vue"
provide(){
    name:computed(()=>{
        this.name
    })
}

这样就完成了数据的双向绑定

vue3全局事件总线

vue3取消了全局事件总线,在这里可以用vue官网推荐的mitt包,可以实现任意组件中的通信

最好把mitt单独封装成一个包eventbus

import mitt from 'mitt'
const emitter = mitt()
export default emitter

这样我们使用的时候直接调用就可以

emitter中有emit,on,all.clear(),off等方法,重点介绍常用的这几个

emitter.emit用来激活事件传递值

import emmiter from './utils/eventbus.js'
send(){
    emmiter.emit("sendData",{name:"scc",age:12})
}

先引入我们封装的包,创建一个send方法,当send被调用,就会激活sendData回调,并且传递{name:"scc",age:12}这个对象

在需要接受数据的组件中用emitter.on监听sendData方法

mounted() {
  emmiter.on("sendData",this.scc)
},

注意,最好在组件生成的时候就开启监听

这样就完成了两个组件中的通信

我们也可以监听所有的事件 ` emmiter.on(*,(type,data)=>{ type代表事件的类型

}) `

*代表所有的事件

当我们不想监听sendData了要怎么做?

mitt作者给我们提供了两种方式 emmiter.all.clear() emmiter.all可以拿到所有的监听的事件,.clear()方法可以取消监听,当然会全部取消

当然我们也可以取消单个事件的监听

emmiter.off(函数名,回调)

只需要传入事件名就可以取消事件的监听

总结

今天早上还学了vite的源码,直接整蒙了,太菜了,加油吧!!!