Vue3中组件数据通信方式总结

 更新时间:2023年06月02日 15:53:19   作者:书源  
如果在面试中,面试官问你Vue组件之间有哪些数据通信方式,你会怎么回复,不要担心,本文为大家整理了超全的Vue3中组件数据通信方式,需要的小伙伴快收藏起来吧

如果在面试中,面试官问你Vue组件之间有哪些数据通信方式,你会怎么回复?

要回答这个问题,我们先来了解一下组件之间数据通信有哪些场景。

如图所示,组件之间数据通信有父子组件之间通信,跨级组件之间通信以及兄弟组件之间通信三种场景,那这三种场景分别有哪些通信手段呢?

父子组件通信

相信大家对这个场景都很熟悉,我这里简单总结下这个场景下的通信方案。

props

在 Vue.js 中实现“父子组件”单向数据通信,一般都是通过 Props 来进行的。

所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,这避免了子组件意外修改父组件状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

每次父组件更新后,所有的子组件中 props 都会被更新到最新值,这意味着我们不应该在子组件中去更改一个 prop。如果做了,Vue 会在控制台上向你抛出警告:

const props = defineProps(['foo'])
// ❌ 警告!prop 是只读的!
props.foo = 'bar'

如果我们在需求中需要更改 prop怎么办?答案是子组件可以抛出一个事件$emit来通知父组件做出改变。

$emit

在子组件中可以直接使用 $emit 方法触发自定义事件,父组件可以通过 v-on (缩写为 @) 来监听事件,然后在监听的回调函数中做出数据的改变。示例:

<!-- 子组件触发事件 -->
<button @click="$emit('someEvent')">click me</button>
<!-- 父组件监听 -->
<MyComponent @some-event="callback" />

通过$emit,子组件可以通过事件参数向父组件传递数据。

不过这种获取子组件数据的方式比较被动,需要等待子组件事件的触发,但一些特殊场合下父组件需要主动获取子组件数据,这时又该如何处理呢?

ref

ref指的是模版引用,它可以直接访问DOM元素,也可以被用在一个子组件上,获取组件实例,进而操作对应元素或者获取数据。

示例,对 DOM 的直接操作:

<script setup>
import { ref, onMounted } from 'vue'
// 声明一个 ref 来存放该元素的引用
// 必须和模板里的 ref 同名
const input = ref(null)
onMounted(() => {
  // 用来从父级组件聚焦输入框
  input.value.focus()
})
</script>
<template>
  <input ref="input" />
</template>

示例,对子组件的直接操作:

<script setup>
import { ref, onMounted } from 'vue'
import Child from './Child.vue'
const child = ref(null)
onMounted(() => {
  // child.value 是 <Child /> 组件的实例
})
</script>
<template>
  <Child ref="child" />
</template>

其它的父子组件通信方式诸如$parent等等,大家请自行理解啦,接下来我们来看下跨级关系的组件如何通信。

跨级组件通信

这个场景下,适合用 provide/inject 进行处理,它允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深。祖先组件中通过 provider 来提供变量,子孙组件中通过 inject 来注入变量,不过它的使用场景,主要是子组件获取上级组件的状态。

我们来看个简单的使用案例:

<script setup> 
import { ref, provide } from 'vue'
// 提供静态值
provide('foo', 'bar') 
// 提供响应式的值
const count = ref(0)
provide('count', count)
</script>
<script setup>
import { inject } from 'vue'
// 注入值的默认方式
const foo = inject('foo')
// 注入响应式的值
const count = inject('count')
</script>

需要说明的是 provide/inject 在父子组件通信中虽然也OK,但更多的场景是子孙组件。

兄弟组件通信

看到这个场景,有没有朋友想到我们可以借助与父组件通信,来完成兄弟组件通信?纵然不看代码,也能想到这种方案十分繁杂。

借用响应式数据文件

于是乎,我们可以考虑换个方案,把通信数据都放在一个响应式数据的文件里,所有通信需要的组件都直接引用这个文件里的数据,然后直接在各自组件间进行读数据或写数据。如果有组件里的模板视图使用到这个公共响应式数据,数据被其它组件修改,那也会同时触发模板视图的更新。这么多文字看着很抽象,我们来看下示例:

store.js,存放响应式数据的文件:

import { reactive } from "vue";
export const store = reactive({
  text: "这里是公共响应式数据文件",
});

B.vue:

<template>
  <div>
    <div>B 组件</div>
    <div>store:{{ store.text }}</div>
  </div>
</template>
<script setup>
import { store } from "./store";
</script>

C.vue:

<template>
  <div>
    <div>C 组件</div>
    <div>store:{{ store.text }}</div>
  </div>
</template>
<script setup>
import { store } from "./store";
</script>

父组件:

<template>
  <div @click="handle">change</div>
  <B></B>
  <C></C>
</template>
<script setup>
import B from "./components/B.vue";
import C from "./components/C.vue";
import { store } from "./components/store";
function handle() {
  store.text = "改变数据文件";
}
</script>

B组件和C组件通过响应式数据文件里的store进行通信,当我们在父组件里改了store.text数据,子组件的视图也会自动更新。

不过聪明的你肯定也发现了,虽然这样兄弟组件可以互相通信,但是呢,一旦公共响应式数据变得庞大,所有引用组件都可以自由修改数据,那么数据流向管理将会变得很混乱,不好管理和维护。

既然我们遇到了这样的问题,别人同样会遇到,于是乎Vue官方为我们提供了Pinia,一个数据管理的 JavaScript 库。

Pinia

这里我想借鉴一下Pinia官网对Pinia的描述,更详细的描述可以参考官网。

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。 而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能:

Devtools 支持

  • 追踪 actions、mutations 的时间线
  • 在组件中展示它们所用到的 Store
  • 让调试更容易的 Time travel

热更新

  • 不必重载页面即可修改 Store
  • 开发时可保持当前的 State

插件:可通过插件扩展 Pinia 功能

为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。

支持服务端渲染

总结

今天我们一起了解了Vue组件通信的3个场景:

父子组件:父组件可以通过props向子组件传递数据,子组件可以通过**$emit** 方法触发父组件接收数据,父组件还可以通过模版引用主动获取子组件数据。

跨级组件:一般通过provider/inject传递数据,其实也可以Pina进行通信

兄弟组件:简单的场景我们可以借助于响应式数据文件来完成通信,复杂的场景可以使用Vue官网提供的Pinia库来管理数据。

到此这篇关于Vue3中组件数据通信方式总结的文章就介绍到这了,更多相关Vue3组件数据通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue2中使用sass并配置全局的sass样式变量的方法

    vue2中使用sass并配置全局的sass样式变量的方法

    这篇文章主要介绍了vue2中使用sass并配置全局的sass样式变量的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • 详解Vue CLI 3.0脚手架如何mock数据

    详解Vue CLI 3.0脚手架如何mock数据

    这篇文章主要介绍了详解Vue CLI 3.0脚手架如何mock数据,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • vue中axios利用blob实现文件浏览器下载方式

    vue中axios利用blob实现文件浏览器下载方式

    这篇文章主要介绍了vue中axios利用blob实现文件浏览器下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Vue启动失败报错:Module not found: Error: Can‘t resolve 'less-loader'解决

    Vue启动失败报错:Module not found: Error: Can‘t resolve &apos

    这篇文章主要给大家介绍了关于Vue启动失败报错:Module not found: Error: Can‘t resolve 'less-loader'解决的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • vue3触发父组件两种写法

    vue3触发父组件两种写法

    这篇文章主要介绍了vue3触发父组件两种写法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • Vue使用Swiper封装轮播图组件的方法详解

    Vue使用Swiper封装轮播图组件的方法详解

    Swiper是一个很常用的用于实现各种滑动效果的插件,PC端和移动端都能很好的适配。本文将利用Swiper实现封装轮播图组件,感兴趣的可以了解一下
    2022-09-09
  • Vue3新属性之css中使用v-bind的方法(v-bind in css)

    Vue3新属性之css中使用v-bind的方法(v-bind in css)

    这篇文章主要介绍了Vue3新属性css中使用v-bind(v-bind in css)的方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • 详解如何理解vue的key属性

    详解如何理解vue的key属性

    这篇文章主要介绍了详解如何理解vue的key属性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 详解Vue计算属性原理

    详解Vue计算属性原理

    计算属性是Vue中比较好用的API,开发者可以利用计算属将复杂的计算进行缓存,同时基于它的响应式特性,我们无需关注数据更新问题,但需要注意的是,计算属性是惰性求值的,本文将详细介绍计算属性的实现原理,需要的朋友可以参考下
    2023-05-05
  • 在pycharm中开发vue的方法步骤

    在pycharm中开发vue的方法步骤

    这篇文章主要介绍了在pycharm中开发vue的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03

最新评论