Vue3的组件间通信

Vue2 的组件间通信

Vue3 的组件间通信:

  1. props
  2. $emit
  3. expose / ref
  4. $attrs
  5. v-model
  6. provide / inject
  7. Vuex
  8. mitt

Vue3 的一些变化(详见文档

  1. 组合式API让Vue3 逻辑关注点聚合,让人不再有一种配置对象的感觉。
  2. teleport 传送组件到指定位置渲染,
  3. 片段,即支持多根节点—多根节点的时候需要,显式指定 attribute 的分布位置
    自定义事件
  4. 单文件组件组合式 API 语法糖 (<script setup>)

Vue3 可以和Vue 2 写一样的结构,这里没有使用和Vue2一样的写法,而是使用单文件组件组合式 API 语法糖 (<script setup>)作为例子(react 版vue,还是vue版react呢,O(∩_∩)O哈哈~)。

props

  父级组件向子组件传递信息,和Vue2 没什么差别,可以和Vue 2 实现的一样,也可以像下面尝试一些新的语法糖。

defineProps 和 defineEmits 都是只在 <script setup> 中才能使用的编译器宏。他们不需要导入且会随着 <script setup> 处理过程一同被编译掉。

<template>
<!-- parent.vue -->
  <HelloWorld msg="Welcome to Your Vue.js App" :msg2="msg" />
</template>
<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { ref } from "vue";
const msg = ref("hello world");
</script>
<template>
<!-- child.vue -->
  <div>{{prop.msg2}}</div>
</template>
<script setup>
// const props = defineProps(['msg2']);
const prop = defineProps({
  msg2:String,
});
</script>

$emit

  Vue3 中组件emit的时候都需要在定义的时候声明(不声明的话会输出一个警告),同时还可以在声明的时候对抛出的事件进行验证,这点变的和 prop 类似;
  同时emits 选项中列出的事件不会从组件的根元素继承,也将从 $attrs property 中移除,孙子组件也就无法触发对应的监听器了。

<template>
<!-- parent.vue -->
{{msg}}
  <HelloWorld msg="Welcome to Your Vue.js App"  @update-data="msg++"/>
</template>

<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { ref } from "vue";
const msg = ref(1);
</script>
<template>
<!-- child.vue -->
  <div @click="emit('update-data')">更新数据</div>
</template>

<script setup>
const emit = defineEmits(['update-data']);
</script>

expose / ref

  expose 用于指定组件实例可以暴露那些属性和方法,没有添加这个属性的时候默认和Vue2 相同暴露全部属性和方法,添加这个属性之后就会只暴露指定的属性和方法了。
  使用 <script setup> 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。所以需要使用 ‘defineExpose’来暴露需要使用的属性和方法。

<template>
<!-- parent.vue -->
{{msg}}
  <HelloWorld ref="Otis" msg="Welcome to Your Vue.js App"  @update-data="msg++" @click="handleClick"/>
</template>

<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { ref } from "vue";

const msg = ref(1);


const Otis = ref(null);
//Otis.value.q  <---- 不能在这里访问,因为这个时候还没有子组件呢
const handleClick = () =>{
  console.log(Otis.value.q);
}
</script>
<template>
<!-- child.vue -->
  <div @click="emit('update-data')">更新数据 {{q}}</div>
</template>
<script setup>
import {ref} from 'vue';
const emit = defineEmits(['update-data']);
const q = ref(56);

defineExpose({
  q,
}) 

</script>

$attrs

  $attrs 现在包含了所有传递给组件的 attribute,包括 class 和 style。

  在 Vue 3 的虚拟 DOM 中,事件监听器现在只是以 on 为前缀的 attribute,这样它就成为了 $attrs 对象的一部分,因此 $listeners 被移除了。

<template>
<!-- parent.vue -->
{{msg}}
  <HelloWorld msg="Welcome to Your Vue.js App"  @update-data="msg++" @up="msg++"/>
</template>

<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { ref } from "vue";

const msg = ref(1);

</script>
<template>
<!-- child.vue -->
  <div @click="emit('update-data')">更新数据 {{q}}</div>
</template>
<script setup>
import {useAttrs} from 'vue';
const emit = defineEmits(['update-data']);
const attrs = useAttrs()  // props和emit 没有接收的属性和监听器都会在这里
console.log(attrs);

</script>

v-model

  支持多个数据进行双向绑定,相当于vue2 中的v-model融合了sync。默认的事件是update:modelValue,默认属性为modelValue。同时v-model 还支持自定义修饰符

<template>
<!-- parent.vue -->
  <HelloWorld msg="Welcome to Your Vue.js App"  v-model:keys="msg" v-model="msg2"/>
</template>

<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { ref } from "vue";

const msg = ref(22);
const msg2 = ref(1);

</script>
<template>
  <!-- child.vue -->
  <div @click="emit('update:keys',a++),emit('update:modelValue',b++)">
    更新数据 {{ props.keys }}--- {{ props.modelValue }}
  </div>
</template>
<script setup>
import { ref } from "vue";

const a = ref(0);
const b = ref(33)
const emit = defineEmits(["update:keys","update:modelValue"]);

const props = defineProps(["keys", "modelValue"]);
</script>

provide / inject

和Vue2 相比变化不大,

<template>
<!-- parent.vue -->
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script setup>
import HelloWorld from "./components/HelloWorld.vue";
import { provide } from "vue";

provide("location", 'Noth Pole');

</script>
<template>
  <!-- child.vue -->
  <div>
    更新数据 {{ out }}
  </div>
</template>
<script setup>
import { inject } from "vue";
const out = inject('location',"defalult value");

</script>

mitt

Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js。

其它

Vue2 中的 $root,$children,$parent,Vuex,slot之类的通信依旧可用没什么变化就不写了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值