vue3组件常用的通信方式有很多,父传子*, 子传父,父直接获取子ref,pinia,pinia在vue3中替换了vuex,更简洁,方便使用操作。EventBus公交车,provide + inject等。
一、父传子(props)
父传子是通过父组件自定义标签添加属性,并传递数据给子组件,子组件接收通过 引入vue插件 解构 defineProps
,调用并创建 props
,同时指定要接收的数据名称。
const props = defineProps(['传递的数据名称'])
案例:
父组件 在views文件夹中创建文件Home.vue
<script setup lang="ts">
// 引入vue插件
import { ref } from "vue"
// 引入子组件
import Son from "../components/Son.vue"
// 定义传递给子组件的数据
const title = ref("我是子组件")
</script>
<template>
<h1>父组件</h1>
<!-- 使用子组件 -->
<Son :title="title"></Son>
</template>
子组件 在components文件夹中创建Son.vue
<script setup lang="ts">
// 引入vue 解构 需要的方法
import { defineProps } from "vue"
// 调用defineProps方法并获取父组件传递的数据
// const props = defineProps(['title'])
const { title } = defineProps(['title']) // 可以简写 解构
</script>
<template>
<!-- 渲染父组件传递的数据 -->
<h1>{{ title }}</h1>
</template>
路由:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
redirect: "/home"
},
{
path: '/home',
name: 'about',
component: () => import('../views/Home.vue')
}
]
})
export default router
效果图:
二、子传父(emit)自定义事件
子传父通过 父组件给子组件标签绑定自定义事件,将事件函数定义在父组件中,子组件中通过从 vue 中解构 defineEmits
,调用并创建emit,同时接收父组件给绑定的事件。调用 emit
触发父组件给绑定的事件,并传递数据,最后父组件在事件函数中通过参数接收子组件传递的数据。
案例:
父组件
<script setup lang="ts">
// 引入vue插件
import { ref } from "vue"
// 引入子组件
import Son from "../components/Son.vue"
// 定义传递给子组件的数据
const title = ref("我是子组件")
const msg = ref('')
// 定义事件函数
const handleAdd = (item: any) => {
msg.value += item
}
</script>
<template>
<h1>父组件</h1>
<!-- 使用子组件
title: 传递给子组件的数据
handleAdd:自定义事件
-->
<Son :title="title" @handleAdd="handleAdd"></Son>
<h3>{{ msg }}</h3>
</template>
子组件
<script setup lang="ts">
// 引入vue 解构 需要的方法
import { defineProps, defineEmits } from "vue"
// 调用defineProps方法并获取父组件传递的数据
// const props = defineProps(['title'])
const { title } = defineProps(['title']) // 可以简写 解构
// 调用defineEmits方法 并接受父组件给绑定的事件
const emit = defineEmits(['handleAdd'])
const handleTitle = () => {
emit("handleAdd", '我是子组件传递的数据')
}
</script>
<template>
<!-- 渲染父组件传递的数据 -->
<h1 @click="handleTitle">{{ title }}</h1>
</template>
效果图:
三、ref()
ref()方法 从vue中解构出 ref
,然后父组件给dome标签或者子组件标签,添加ref属性,值是已经定义好的ref
空数据的变量名称。
子组件从vue中解构出defineExpose
,调用并想外暴露你想要获取的数据/方法
父组件通过从vue中解构生命周期onMounted
,调用onMounted
生命周期在里面 通过调用ref的数据value
获取到 dome标签 或 子组件实例对象。
案例:
父组件
<script setup lang="ts">
// 引入vue插件
import { ref, onMounted } from "vue"
// 引入子组件
import Ref from "../components/Ref.vue";
// 定义ref
const myref = ref()
onMounted(() => {
console.log(myref.value, '');
// ref组件定义的数据
console.log(myref.value.message);
// 调用 ref组件中暴露出的方法
myref.value.handleAdd()
})
</script>
<template>
<h1>父组件</h1>
<!-- 定义ref -->
<Ref ref="myref"></Ref>
</template>
子组件
<script setup lang="ts">
// 引入vue
import { defineExpose, ref } from "vue"
// 定义数据
const message = ref("我是Ref子组件中的数据")
// 定义方法
const handleAdd = () => {
console.log('我是Ref子组件中的方法');
}
// 通过 defineExpose 将数据方法暴露出去
defineExpose({
message,
handleAdd
})
</script>
<template>
我是ref方法
</template>
效果图:
四、pinia
Vuex 和 Pinia 是 Vue 3 中的全局状态管理工具,使用这两个工具可以轻松实现组件通信。
它们都是全局的、所有组件都可以访问的、存储数据和方法,用来管理组件中的共享状态的仓库。并且能够在整个组件中进行访问和修改。让我们更有效的 组织 和 管理 整个组件的状态,使我们更轻松的开发复杂的、大型数据的前端项目。
同时解决了同步异步对调试工具的影响 和 代码的耦合性 还有组件之间数据通信的混乱问题。
使用pinia 首先我们需要先下载安装
npm install pinia
- 然后需要在
main.js/ts
中配置 - 创建仓库文件夹(stores),同时定义仓库文件
仓库文件的内容
- 导入
创建仓库
- 定义数据/方法
- 导出仓库
// 导入 import { defineStore } from "pinia"; import { ref } from "vue" // 创建仓库 const tableStore = defineStore("table", () => { // 定义数据 let count = ref(0) // 定义方法 const changeCount = () => { // 数量自增 count.value++; } const changeDrop = () => { // 数量自减 count.value--; } // 返回 数据 和 方法 return { count, changeCount, changeDrop } }) // 导出仓库 export default tableStore
在组件中使用
<script setup lang="ts"> // 引入vue插件 import { ref, onMounted } from "vue" // 引入仓库 import tableStore from "../stores/table" // console.log(tableStore().count); // 定义数量加加的方法 const handleCountAdd = () => { // 调用仓库中数量加加的方法 tableStore().changeCount() } // 定义数量减少的方法 const handleCountDrop = () => { // 调用仓库中数量减少的方法 tableStore().changeDrop() } </script> <template> <h1>父组件</h1> <!-- 渲染仓库数据 / 方法调用--> <button @click="handleCountAdd">+</button> <h2>{{ tableStore().count }}</h2> <button @click="handleCountDrop">-</button> </template>
效果图:
注意事项:默认从pinia仓库中获取到的数据不是响应式的,变成响应式,使用以下三个方案:
- 定义依赖仓库数据 得到 新数据 的 计算属性 数据
- 使用vue的组合式API中的toRef将仓库中的某个数据转换成行。
*
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。