Vue3中组件通信
1.方式1:defineProps
defineProps通常用于在单文件组件中,父组件向子组件传递数据。
1.1 示例
父组件 blog.vue
// Blog.vue
子组件 Article.vue
//Article.vue
const props = defineProps({ title: String, ... })
而实际上,value还可以为一个对象,其中对props的相关信息进行了设定,包括:
type— props的类型,如果可能存在多个类型,则可以写成数组形式,例如:[String,Number]default— 该props的默认值require— 是否为必传项,默认为false。
以上面的title为例,其实际上可以写成:
const props = defineProps({ title: { type: String, default: '111', require: false, } })
以字符串数组形式声明时,数组的每一项字面量就为prop对应的名称。
const props = defineProps(['title', 'info', 'author']);
其次,关于props的使用:
在 template 模版中,直接使用defineProps()中声明的名称。
在 setup 中,只需要直接props.xxx就可以获取到该props对应的值。
另外,还需要注意:
1.props一般是单向的,所以在子组件中不应该对 props 进行修改。如果需要在子组件中对props进行处理,应当使用ref对props进行处理后,再进行修改。
const formatTitle = ref(props.title)
//这样,子组件中后续对 formatTitle 的修改,就与原props.title 无关联了
2.当父组件传递的为一个对象时,例如对于上面的例子:
<!-- 也可 →
此时,子组件中的声明不需要改变,但是需要将该对象中将会用到的属性值通过defineProps声明出来。
3.在向子组件传递数据时,注意组件上用v-bind绑定的值不要重复,也不要与组件本身的属性重名!
2.defineEmits
同样地,defineEmits也常用于单文件组件的组件间通信,但其多用于子组件向父组件传递数据。
2.1 示例
父组件
子组件
其效果实际上就是点击后,子组件中的value加一。
下面对该示例进行说明。
首先,在父组件中,向子组件传递了一个num的props用于展示数据。
同时,在父组件中定义了一个名为 increase 的监听事件以及事件触发后的处理函数(即把num加一)。
而在子组件中,添加了一个点击事件,在该事件的处理函数中,通过对象emit触发了父组件的 increase 监听事件,导致num加一。
2.2 具体用法
defineEmits和defineProps一样,不需要引入,可以在 setup 函数中直接使用。
defineEmits可以用于声明对父组件上的一个或多个监听事件的触发,并返回一个触发函数对象emit。
下面是声明方式:
const emits = defineEmits(['increase']); // 声明多个触发 const emits = defineEmits(['increase', 'emit2', 'emit3']);
如何使用触发?
// 要触发哪个监听事件,就传入对应的事件名 emits('increase'); emits('emit2');
2.3 说明
关于emits()的参数:
- 第一个参数,是监听事件的字面量(即名称)。
- 第二个参数为事件传递的参数。如果该事件有多个参数,第二个参数建议用对象的形式传递。
例如:
//子组件发送,传递两个参数 emits('increase', {params1:'1',params2:'2'}); ... //父组件监听事件的处理函数 const handleIncrease = (params) => { console.log(params.params1, params.params2);//{'1','2'} nums.value += datas; };
3. $ref + defineExpose
这种方法通常用于实现父子组件之间的通信。
在 vue2 中,有时候想访问refs。
但在 vue3 中,由于在 setup 中无法访问到 this,所以这种方式是不适用的!那么为了能够使用 $refs,我们需要借助一个方法:getCurrentInstance()。该对象返回当前的实例对象,但在使用该方法时,需要注意:
- 不要将该函数当作一个 optionsApi 来获取 this
- 该方法仅在 setup、生命周期函数中有效,在方法中是无效的。
3.1 实例
父组件
子组件
这里需要注意的是:在使用<script setup>语法糖时,组件是默认关闭的,即:在父组件中通过$refs来访问子组件中的值或在子组件中通过$parents来访问父组件中的值时,都是取不到的!必须通过defineExpose暴露对应值后,才可以被访问到。
3.2 说明
实际上,在开发中,上面使用$refs的方式并不多见,因为其必须要依靠getCurrentInstance()方法。
使用较多的是下面这种方法:
或者可以这样:
即在<script setup>语法糖中,可以不用返回,因为其中的值为自动返回。
接下来就可以通过声明的响应式对象来使用对应组件中通过defineExpose暴露出来的属性了!
4.其它方法
vue3中除了以上三种组件间通信的方式,还有其它可以实现组件间通信的方法:
- v-model
- 依赖注入 provide / inject
- eventBus
- vuex
其中,v-model 并不能严格成为数据的传递方式,其实只是减少了代码量。
而关于 eventBus,虽然 vue3 中将其移除,但仍然可以通过第三方插件来使用。