vue3组件通信

172 阅读2分钟
1. props/emit、v-model 解决父子传信

先解决一下,总结toRef知识点的时候提的问题,将props去toRef或toRef将属性转为ref数据会将传递的props变为双向数据流嘛? 答案是不会🤭,我打印看了一下props,发现是被readonly定义过的。之前说过readonly会递归将传入的数据所有的属性都变成只读不可修改的。

父组件

<template>
  <SetupEx v-model:msg="msg" @changeMsg="changeMsg" />
</template>

<script setup lang="ts">
import {ref} from 'vue'
const msg = ref('小刘同学');
</script>

子组件两种模式

// options 
import {toRefs} from 'vue';
setup(props, context) {
    const {msg} = toRefs(props)
    // 这里使用传统props/emit方式
    context.emit('changeMsg')
    return {
        msg
    }
}


// script setup
<script setup lang="ts">
interface Props {
    msg?: string,
    id?: string
}
const props = defineProps<Props>();
const {msg} = toRefs(props);
// 这里使用v-model模式
const emit = defineEmits(['update:msg']);
emit('update:msg', '小刘同学被修改了!!!')
</script>
  • 为了省事几种情况我综合在了一起,测试的时候直接把没用的代码删掉就行。
  • 如果仔细观察会发现,我拿到props之后是用toRefs解构出单独属性,解构如果不用toRefs定义一下会丢失响应式,父组件值修改,子组件将不会同步修改。如果你不用解构直接拿着props去展示将不会有这种问题
2. eventBus

和vue2一样的,事件派发和事件监听,这里用法都一样的。只要组件没有被销毁都是可以监听接收消息的,可以解决祖孙、兄弟组件等的传信。

3. provide/inject 祖孙传信

用法和vue2有一些区别,响应式更方便了,直接将provide传递的值用ref或者reactive定义一下就ok了🐂🍺,之前vue2的时候从来不用这玩意,感觉很难用。如果后面换vue3的话,我想我会经常用的👍

祖先

<script setup lang="ts">
import {provide, ref} from 'vue';

const bol = ref(true)
provide('flag', bol)
const changeProvide = () => {
  bol.value = !bol.value;
}
</script>

祖孙

<template>
    <div>flag-是-{{flag}}</div>
</template>

<script setup lang="ts">
import {inject, ref} from 'vue';
const flag = inject('flag')
</script>
4. ref

懒人大概都比较熟悉这个属性😏,vue3用法有些许的变化,想要的获取的子组件属性需要被暴露出来,父祖件拿到ref实例的方式也有一下变化,详细见下面代码

子组件

<script setup lang="ts">
import {ref, Ref, nextTick, defineExpose, reactive} from 'vue';
interface Obj {
    name: string
}
const obj = reactive<Obj>({
    name: '小刘同学'
})
defineExpose({
    obj
})
</script>

父组件

<template>
  <comp ref="SetupExRef" />
</template>

<script setup lang="ts">
import comp from './comp'
import {ref, Ref, nextTick} from 'vue';
const setupExRef = ref<null | Ref>(null)
nextTick(() => {
    console.log(CusCompRef.value.obj); //小刘同学
})
</script>
5. parent/chldren

懒人肯定知道这俩获取父组件/子组件实例的方法, setup里面没有了this怎么办?也是有方法拿到的😔,getCurrentInstance看名字就能知道获取当前组件实例的,只支持在setup中使用或者生命周期里

import { defineComponent } from 'vue';
console.log(getCurrentInstance())

领导找你的时候别说我告诉你们的哈🐕

6. 还有一个是状态管理器vuex/pinia

pinia 算是vuex5这个得专门开一篇总结