Vue3 数据通信

news2024/11/24 6:32:40

一、基本概念

数据在 vue 中是单向流动的,有利于管理数据状态和变化。
而在日常组件开发中,难以避免组件之间的数据通信。组件通信可以分为不同的场景,例如父子组件通信、兄弟组件通信、跨层级组件通信等。
Vue3 提供了多种方式进行组件间的通信:

  • props: 自上而下传递数据
  • emit: 自下而上报事件
  • provide/inject: 跨层级传递数据
  • v-model: 双向绑定
  • expose/ref: 暴露组件实例的方法和数据
  • pinia/vuex: 状态管理库
  • eventBus/eitt: 全局事件总线

二、props/emit

props 用于父组件向子组件传递数据,子组件通过定义 props 来接收数据。数据流动是单向的,子组件只能接收数据,不能修改。
$emit 用于子组件向父组件发送事件通知,父组件可以根据这些事件执行相应的逻辑或更新状态。

<!-- 父组件  -->
<template>
  <ChildComponent :message="parentMessage" @childClicked="handleChildClick" />
</template>

<script setup>
import ChildComponent from './childComponent.vue'
import { ref } from 'vue'

const parentMessage = ref('Hello from Parent Component!')
const handleChildClick = (val) => {
  parentMessage.value = val
}
</script>
-------------------------------------------------------------------------------------------
<!-- 子组件 -->
<template>
    <p>parentMessage: {{ props.message }}</p>
    <button @click="notifyParent">Click Me</button>
  </template>
  
<script setup>
import { defineProps, defineEmits } from 'vue'
const props = defineProps({
    message: String
})
const emit = defineEmits(['childClicked'])
const notifyParent = (val) => {
    val = 'Hello from Child Component!'
    emit('childClicked', val)
}
</script>

子组件接收的变量要与父组件冒号后的变量一致,父组件 @ 后面的事件名要与子组件 emit 的事件名一致

三、provide/inject

依赖注入解决的问题是:有多层级嵌套的组件,形成了一棵巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦。
在这里插入图片描述
provide 和 inject 就可以帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。
在这里插入图片描述


<!-- 祖先组件 -->
<template>
    <DescendantComponent />
</template>
  
<script setup>
import { provide } from 'vue'
import DescendantComponent from './descendantComponent.vue'

const ancestorValue = 'I provided from Ancestor Component!'
provide('sharedValue', ancestorValue)
</script>
--------------------------------------------------------------------------------------------
<!-- 后代组件 -->
<template>
    <grandchildComponent />
</template>

<script setup>
import GrandchildComponent from './grandchildComponent.vue'
</script>
--------------------------------------------------------------------------------------------
<!-- 孙组件 -->
<template>
    <p>祖先数据:{{ grandchildValue }}</p>
</template>

<script setup>
import { inject } from 'vue'

const grandchildValue = inject('sharedValue', 'default value')
</script>

inject 的第一个参数要和 provide 第一个参数一致,它第二个参数是可选的,即在没有匹配到 key 时使用的默认值。第二个参数也可以是一个工厂函数,用来返回某些创建起来比较复杂的值。在这种情况下,必须将 true 作为第三个参数传入,表明这个函数将作为工厂函数使用,而非值本身。

四、v-model

v-model 用于在父子组件之间实现双向数据绑定,Vue3 支持多个 v-model 绑定。使用 v-model 的时候,在子组件中一定要使用update:XXX开头的,绑定的变量就是父组件v-model:后的变量
应用场景: 用于在组件之间进行双向数据绑定,如表单输入组件、计数器等。

<!-- 父组件  -->
<template>
  <childComponent v-model:count="parentCount" />
  <p>Parent Count: {{ parentCount }}</p>
</template>

<script setup>
import childComponent from './childComponent.vue'
import { ref } from 'vue'

const parentCount = ref(0)
</script>
-------------------------------------------------------------------------------------------
<!-- 子组件 -->
<template>
    <button @click="increaseCount">Increase Count</button>
  </template>

<script setup>
import { defineEmits, defineProps } from 'vue'
const props = defineProps(['count'])
const emit = defineEmits(['update:count'])
const increaseCount = () => {
    emit('update:count', props.count + 1)
}
</script>

五、expose/ref

expose 和 ref 可以让子组件暴露某些方法或属性给父组件或其他组件访问,expose 用于定义子组件暴露的 API,ref 用于在父组件中引用子组件的实例并调用暴露的方法。

<!-- 父组件 -->
<template>
  <button @click="callChildMethod">Call Child Method</button>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './childComponent.vue'

const childRef = ref(null)
const callChildMethod = () => {
  childRef.value?.doSomething()
}
</script>
--------------------------------------------------------------------------------------------
<!-- 子组件 -->
<template>
    <button @click="doSomething">Do Something</button>
</template>

<script setup>
import { defineExpose } from 'vue'
const doSomething = () => {
    alert('Doing something')
}
defineExpose({ doSomething })
</script>

六、vuex

vuex 是 vue 的官方状态管理库,用于集中管理应用的状态,并提供机制来更新状态,适用于大型应用中多个组件共享状态的场景。
应用场景: 适用于需要管理全局状态的应用,如用户信息、购物车内容等。

// store.js
import { createStore } from 'vuex'
const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    add(state) {
      state.count++
    },
    sub(state) {
        state.count--
    }
  },
  actions: {
    add({ commit }) {
      commit('add')
    },
    sub({ commit }) {
      commit('sub')
    }
  },
  getters: {
    getCount(state) {
      return state.count
    }
  }
})
export default store
--------------------------------------------------------------------------------------------
<!-- 组件 add -->
<template>
    <div>
      <p>Count: {{ count }}</p>
      <button @click="add">+1</button>
    </div>
</template>

<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'

const store = useStore()
const count = computed(() => store.getters.getCount)
const add = () => store.dispatch('add')
</script>
--------------------------------------------------------------------------------------------
<!-- 组件 sub -->
<template>
    <div>
      <p>Count: {{ count }}</p>
      <button @click="sub">-1</button>
    </div>
</template>

<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'

const store = useStore()
const count = computed(() => store.getters.getCount)
const sub = () => store.dispatch('sub')
</script>

七、pinia

pinia 是 Vue3 的官方状态管理库,作为 vuex 的替代品,提供了一个更简洁的状态管理方案,支持 TypeScript,易于使用和扩展。

// countStore.js
import { defineStore } from 'pinia'
export const useCountStore = defineStore('count', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
})
-------------------------------------------------------------------------------------------
<!-- 组件 add -->
<template>
  <div>当前count: {{ counter.count }}</div>
  <button @click="counter.increment">+1</button>
</template>

<script setup>
import { useCountStore } from '@/stores/countStore'
const counter = useCountStore()
</script>
-------------------------------------------------------------------------------------------
<!-- 组件 sub -->
<template>
  <div>当前count: {{ counter.count }}</div>
  <button @click="counter.decrement">-1</button>
</template>

<script setup>
import { useCountStore } from '@/stores/countStore'
const counter = useCountStore()
</script>

八、eventBus

eventBus 是一种简单的事件发布/订阅模式,事件总线允许组件之间通过发布/订阅模式传递事件,但在大型应用中可能导致事件流动复杂,推荐使用其他状态管理工具。
在 Vue3 中,推荐使用 mitt 作为事件总线的实现,它提供了一个简单的 API 来处理事件总线。
应用场景: 适用于小型应用或临时的组件间通信需求。

// eventBus.js
import mitt from 'mitt'
export const emitter = mitt()
--------------------------------------------------------------------------------------------
<!-- 组件 A -->
<template>
  <button @click="sendMessage">Send Message to B</button>
</template>

<script setup>
import { emitter } from '../../eventBus'
const sendMessage = () => {
  emitter.emit('message', 'Hello from Component A!')
}
</script>
--------------------------------------------------------------------------------------------
<!-- 组件 B -->
<template>
  <p>当前message: {{ message }}</p>
</template>

<script setup>
import { ref } from 'vue'
import { emitter } from '../../eventBus'

const message = ref('默认信息')
emitter.on('message', (msg) => {
  message.value = msg
})
</script>

发布信息方用 emit,接受信息方用 on

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无法访问,你可能没有权限使用网络资源,此用户无法登录

解决方法&#xff1a; 打开控制面板&#xff0c;WinR运行框输入 control 控制面板主页更改为小图标&#xff0c;并选择凭据管理器 选择Window凭证&#xff0c;添加凭证&#xff08;如果之前输错过的&#xff0c;这里会有信息&#xff0c;请删掉重新添加&#xff09;

Mysql基础练习题 620.有趣的电影 (力扣)

620.编写解决方案&#xff0c;找出所有影片描述为 非 boring (不无聊) 的并且 id 为奇数 的影片,返回结果按 rating 降序排列 题目链接&#xff1a; https://leetcode.cn/problems/not-boring-movies/ 建表插入数据&#xff1a; Create table If Not Exists cinema (id int…

HIS系统|HIS系统成品|HIS系统应用

随着医疗信息化的飞速发展&#xff0c;HIS&#xff08;医院信息系统&#xff09;已经成为现代医院不可少的组成部分。HIS系统在医疗行业中扮演着至关重要的角色&#xff0c;广泛应用于医院的各个环节&#xff0c;不仅提高了医疗服务的效率&#xff0c;也增强了患者体验。本文将…

Vision Transformer (ViT) + 代码【详解】

文章目录 1、Vision Transformer (ViT) 介绍2、patch embedding3、代码3.1 class embedding Positional Embedding3.2 Transformer Encoder3.3 classifier3.4 ViT总代码 1、Vision Transformer (ViT) 介绍 VIT论文的摘要如下&#xff0c;谷歌翻译如下&#xff1a; 虽然 Transf…

JVM面试(四)类加载器和双亲委派机制

什么是类加载器&#xff1f; 简单来说的话&#xff0c;是用于实现“类加载动作”的加载器 “通过一个类的全限定名来获取描述该类的二进制字节流”这个动作放到Java虚拟机外部去实现&#xff0c;以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器…

Web测试(知识总结)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 随着Internet和Internet/Extranet的快速增长&#xff0c;Web已经对商业、工业、银行、财政、教育、政府和娱乐及我们的工作和生活产生了深远的影响。许多传统的…

代码随想录打卡第10天

232 用队列实现栈 两个栈一个负责入一个负责出。 class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;public MyQueue() {stackInnew Stack<>();stackOut new Stack<>();}public void push(int x) {stackIn.push(x);}public int pop() {…

axure9勾选多个删除,弹框显示多个中继器编号

文本框 情形是删除逗号 文本框内插入数据

分类预测|基于雪消融优化极端梯度提升的数据分类预测Matlab程序SAO-XGBoost 多特征输入多类别输出

分类预测|基于雪消融优化极端梯度提升的数据分类预测Matlab程序SAO-XGBoost 多特征输入多类别输出 文章目录 一、基本原理SAO&#xff08;雪消融智能优化算法&#xff09;回归预测中的应用XGBoost 回归预测基本原理SAO-XGBoost 流程 二、实验结果三、核心代码四、代码获取五、总…

Json数据解析报错 -TAB

表现&#xff1a; n8n 解析服务器的数据 报错 json 解析错误 原理&#xff1a; tab键 在代码中为 string tab \t解决办法&#xff1a;tab键替换4个空格 string tab "\t" tab.replaceAll("\t", " ")问题&#xff1a; tab 键 和 空格 在普…

特殊教育学校自闭症:提供个性化教学,满足孩子需求

在特殊教育领域&#xff0c;针对自闭症儿童的个性化教学已成为一种趋势&#xff0c;旨在通过量身定制的教育方案&#xff0c;最大限度地满足每位孩子的独特需求。星启帆自闭症儿童康复机构&#xff0c;作为广州地区的一颗璀璨明珠&#xff0c;正是这一理念的忠实践行者。 星启帆…

什么叫3d建模渲染?与云渲染农场关系

3D建模渲染行业是一个涉及多个行业和领域的技术过程&#xff0c;它不仅仅是一个特点行业的产物&#xff0c;而是广泛应用于产品设计、工业设计、环境设计、动画、游戏建模和影视CG等多个领域。那么3D建模渲染又与云渲染农场有什么关系呢&#xff0c;一起来简单看看吧。 什么叫3…

音频原始数据PCM

PCM全称是脉冲编码调制数据。PCM数据是未经过压的音频数据&#xff0c;它由模拟信号信号经过采样、编码等步骤抓换成的数字信号。 一、音频基础知识讲解 1.1频率 声音是由震动产生的&#xff0c;所以声音是有频率的&#xff0c;人类可以听到的声音频率大概在20HZ~20KHZ 1.2振…

宠物空气净化器真的有用吗?去浮毛好用的宠物空气净化器推荐

不知不觉我已经养宠五年了&#xff0c;一人两猫作伴的日子充满着幸福&#xff0c;可猫毛的存在偶尔也会让小家出现裂缝。每当换毛季&#xff0c;我的鼻子就率先作出反应&#xff0c;瘙痒加上止不住喷嚏都在反映着不佳的空气质量。这都是因为猫咪疯狂掉毛&#xff0c;浮毛上附着…

最新车型库大全|阿里云实现调用API接口

整体请求流程&#xff1a; 介绍&#xff1a; 本次解析通过阿里云云市场的云服务来实现查询车型库大全查询&#xff0c;首先需要选择一家可以提供查询的商品。 [探数API]车型库查询_API专区_云市场-阿里云 步骤1: 选择商品 如图点击免费试用&#xff0c;即可免费申请该接口数…

Power BI Desktop突然自动关闭如何恢复未保存的开发内容?

故事背景 今天有位同事在用Power BI Desktop开发报告的时候&#xff0c;Power BI Desktop软件突然自动关闭时&#xff0c;更让同事郁闷的是开发了两个小时的报告内容还未点击保存&#xff01; 同事非常担心会丢失未保存的报告开发内容&#xff0c;找我寻求帮助如何恢复未保存…

无人机培训校企合作技术详解

随着无人机技术的飞速发展&#xff0c;其在航拍、农业、环境监测、应急救援等多个领域展现出巨大的应用潜力&#xff0c;市场对无人机专业人才的需求也日益增长。因此&#xff0c;加强无人机培训领域的校企合作&#xff0c;成为培养高素质无人机技术人才的重要途径。本文将从合…

企业为什么要使用加密软件?哇!原来有这么多好处呢

1、防止内部泄密&#xff1a;加密软件可以限制文件的访问权限&#xff0c;防止机密文件在公司内部随意流转。 2、访问控制&#xff1a;加密软件可以设定严格的访问控制策略&#xff0c;确保只有授权用户才能访问敏感数据。 3、提升数据恢复能力&#xff1a;通过加密备份数据&…

redis学习(011 实战:黑马点评:优惠券秒杀:redis实现全局唯一ID)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第48p-第p49的内容 文章目录 全局唯一ID编码 全局唯一ID //String did dao.haveKeyId(“deputybedthing”); 这里的主键并没有…

基于微信小程序在线订餐系统

微信小程序在线订餐系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序在线订餐系统的开发全过程。通过分析微信小程序在线订餐系统管理的不足&#xff0c;创建了一个计算机管理微信小程序在线订…