Vue3 组件之间的通信

一、父子通信

① props 父传子(这种传值方法是只读的,不可以进行修改

父组件props.vue中

<template><h2>props:我是父组件</h2><hr><props-child msg="我是静态的数据" :num="num" :obj="{ name:'小黑',age:18 }"></props-child>
</template><script setup lang="ts"> 
import { ref } from 'vue'
// props:可以实现父子组件的通讯,props数据还是只读的(不能修改!!)
import propsChild from './propsChild.vue';
let num = ref(521)
</script>

子组件 propsChild.vue 中接收数据

<template><h2>propsChild:我是子组件</h2><!-- 在模板使用时,可以直接省略前面的props(两种方式都可以) --><div>{{msg}}----{{num}}</div><div>{{props.msg}}----{{props.num}}</div><div>{{ obj.name }}---{{ obj.age }}</div>
</template><script setup lang="ts"> 
// v3使用的是defineProps方法接收父组件传递过来的数据(不需要引入直接使用)// const props = defineProps(['msg','num']) //  1、 可以写数组也可以写对象
/** 第二种写法,有默认类型和默认参数。
const props = defineProps({msg:{type:String,//接受的数据类型default:'默认参数',//接受默认数据},num:{type:Number,default:0}
})
*/
interface Iprops {name:string,age:number
}
const props = defineProps<{msg:String,num:Number,obj:Iprops
}>()
</script>

② 子给父传 (自定义事件 使用defineEmits(['xxx'])

eventChild.vue 子组件通过一个事件去触发传值

  <template><div>eventChild</div><button @click="handleClick">子组件按钮</button></template><script setup lang="ts">// 利用defineEmits方法返回函数触发自定义事件(不需要引入直接用)// 未用 Ts 写法   // const emit = defineEmits(["event"])// const handleClick = () => {//     emit('event','小黑')// }//用ts写法const emit = defineEmits<{(e:'event',myvalue:string):void}>()const handleClick = () => {emit('event','小黑'); //提交第一个参数是事件名 ,后面都是携带的参数}</script>

eventFather.vue 父组件通过自定义事件接收

<template><h2>event1</h2><EventChild @event="eventFn"></EventChild>
</template><script setup lang="ts">
import EventChild from './eventChild.vue'const eventFn = (val) => {console.log(val);
}
</script>

二、兄弟通信(全局事件总线)

需要借助插件 mitt

npm install --save mitt

① 引入(新建bus文件夹创建index.ts)

 暴漏出方法 

// 引入mitt :注意mitt是一个方法,执行后会返回bus对象
import mitt from "mitt";
const bus = mitt()
export default bus

 ② 兄弟之间传值eventBus1和eventBus2

③ 父级eventBus使用两兄弟

<template><h2>eventBus全局总线</h2><EventBus1></EventBus1><EventBus2></EventBus2>
</template><script setup lang="ts">
import EventBus1 from './eventBus1.vue'
import EventBus2 from './eventBus2.vue'
</script>

  ④  eventBus2 传值给 eventBus1

<template><h3>eventBus2</h3><button @click="handler">点击给eventBus1传值</button>
</template><script setup lang="ts">
import bus from '../../bus'
const handler = () => {   //emit(送东西)bus.emit('msg', { name: '小黑'})
}
</script>

⑤ eventBus1接收

<template><h3>eventBus1</h3>
</template><script setup lang="ts">
import bus from '../../bus/'
import { onMounted } from 'vue';
onMounted(()=> {// 第一个参数:为事件的类型,第二个参数为事件的回调bus.on('msg',(val)=> {   //on(收东西!!)console.log('val',val);})
})
</script>

三 、v-model (父子组件数据同步)

v-model指令:手机表单数据,数据双向绑定 v-model也可以实现组件之间通信,实现父子组件数据同步业务。 这个v-model就是把defineProps和defineEmits 结合起来 使用父传子到子传父形成数据同步 可以同时绑定多个v-mdoel。

1、写一个

① 父组件 vModel.vue

<template><h4>v-model(父组件)---{{num}}</h4><vModelSon1 v-model="num"></vModelSon1> <!--  v-model相当于下面这个写法 相当于简化了--> <vModelSon1 :modelValue="num" @update:modelValue="handler"></vModelSon1> 
</template><script setup lang="ts">
import { ref } from 'vue';
import vModelSon1 from './vModelSon1.vue'let num = ref(100)
const handler = (sonNum) => {// 接收子组件传的数据num.value = sonNum
}
</script>

② 子组件vModelSon1.vue

<template><div style="background:#ccc"><div><h4>vModelSon1(子组件)</h4></div><div>{{ modelValue }} ----接收父组件的值 </div><button @click="sonClick">子组件按钮</button></div>
</template><script setup lang="ts">let props = defineProps(['modelValue'])let emit = defineEmits(['update:modelValue'])const sonClick = () => {emit('update:modelValue',props.modelValue+2)}
</script>

 2、写多个

① 父组件 vModel.vue

<template><h4>v-model(父组件)---num: {{num}}--num1: {{ num1 }}</h4><!-- 就相当于传了两个props 而且相当于给子组件绑了两个自定义事件update:num和update:num1 --><vModelSon2 v-model:num="num" v-model:num1="num1"></vModelSon2> 
</template><script setup lang="ts">import { ref } from 'vue';import vModelSon2 from './vModelSon2.vue'let num = ref(100)let num1 = ref(200)
</script>

② 子组件vModelSon2.vue

<template><h4>vModelSon2(同时绑定多个v-model)</h4><button @click="numClick">{{ num }}</button><button @click="num1Click">{{ num1 }}</button>
</template><script setup lang="ts">
let props = defineProps(['num','num1'])
let emit = defineEmits(['update:num','update:num1'])
const numClick = () => {emit('update:num',props.num+2)
}
const num1Click = () => {emit('update:num1',props.num1+4)
}
</script>

即可完成父子组件数据同步

四、useAttrs

 vue3框架提供了一个方法useAttrs方法,可以获取到组件身上的属性和事件

和props一样 二者之中props如果声明了接收的值,那么useAttrs就接收不到了、 父组件中间照常写给子组件传值的代码

① 父组件attrs.vue

<template><h3>父组件attrs</h3><attrsSon type="primary"  title="名字" @event="handleEvent" @xxx="handle"></attrsSon>
</template><script setup lang="ts"> 
import attrsSon from './attrsSon.vue';
const handleEvent = () => {}
const handle = () => {}
</script>

 ② 子组件attrsSon.vue

<template><div>子组件:{{ attrs.title }}</div>
</template><script setup lang="ts">
// 引入useAttrs方法:获取组件(attrsSon)身上的属性和事件
import { useAttrs } from 'vue';
// 此方法会返回一个对象
let attrs = useAttrs()
console.log('attrs',attrs);// 注:useAttrs和defineProps同时存在则defineProps优先级高
</script>

五、ref 和 $parent (父子通信) 加上defineExpose对外暴露来拿到数据进行修改

① 通过 ref ( 父组件可以拿到子组件的属性和方法 )

 父组件refather.vue

<template><div style="color:#0ee993">父组件的数量:{{ num }}</div><button @click="fatherBtn">父按钮</button><refParentSon ref="sonRef"></refParentSon>
</template><script setup lang="ts">
import refParentSon from './ref-parent-son.vue'
import {ref, getCurrentInstance} from 'vue'
/** 
// 获取子组件的实例
const { proxy } = getCurrentInstance();   
proxy.$refs.sonRef
*/
let num = ref(100)// 获取子组件的实例
let sonRef = ref()
const fatherBtn =() => {num.value+=2sonRef.value.num-=2  //子组件的属性sonRef.value.fn()  //子组件的方法
}
</script>

子组件refParentSon.vue

<template><div style="color:#000993">子组件的数量:{{ num }}</div>
</template><script setup lang="ts">
import {ref} from 'vue'
let num = ref(10)
const fn = () =>{ console.log('我是子组件的方法')}// 组件内部的数据对外关闭,如若想对外使用需通过defineExpose方法暴露
defineExpose({num,fn
})
</script>

① 通过$parent ( 可以在子组件内部获取到父组件的实例 )

父组件refather.vue

<template><div style="color:#0ee993">父组件的数量:{{ num }}</div><refParentSon1></refParentSon1>
</template><script setup lang="ts">
import refParentSon1 from './ref-parent-son1.vue'
import {ref} from 'vue'
let num = ref(100)  //父组件的数据
const fatherFn = () => {console.log('父组件的方法')}//父组件暴露数据
defineExpose({num,fatherFn
})</script>

子组件ref-parent-son1.vue

<template><div style="color: green">子组件的数量:{{ num }}</div><button @click="sonClick($parent)">子按钮</button>
</template><script setup lang="ts">
// 子组件内部拿父组件的数据
import {ref} from 'vue'
let num = ref(10)
const sonClick = ($parent) => {num.value+=2$parent.num-=2  //子组件拿父组件数据$parent.fatherFn() //子组件拿父组件方法
}
</script>

六、provide 和 inject

vue3提供provide(提供)与inject(注入)可以实现隔辈组件传递数据  

父有子组件、子有孙组件(父组件数据儿可以用,孙也可以用)

  ① 父组件(祖先组件)provideAndInject.vue 中

<template><div style="background-color:pink">父组件: <provideAndInjectSon></provideAndInjectSon></div>
</template>
<script setup lang="ts">import provideAndInjectSon from './provideAndInjectSon.vue'
//vue3提供provide(提供)与inject(注入)可以实现隔辈组件传递数据   import {ref,provide} from 'vue'let msg = ref('我是祖先数据')// 第一个参数是提供的数据key 第二个参数是提供的数据 provide("Tian",msg)
</script>

② 儿组件 provideAndInjectGrandson.vue 中

<template><div style="border:1px solid red">我是儿子用父的数据---{{msg}}<provideAndInjectGrandson></provideAndInjectGrandson></div>
</template><script setup lang="ts">import {inject} from 'vue'import provideAndInjectGrandson from './provideAndInjectGrandson.vue'//需要的参数:即为祖先提供的keylet msg = inject('Tian')console.log('msg',msg);
</script>

③ 孙组件 provideAndInjectGrandson.vue 中

<template><div style="background:green">我是孙子用父的数据---{{msg}}</div>
</template><script setup lang="ts">import {inject} from 'vue'let msg = inject('Tian')console.log('msg',msg);
</script>

七、任意组件之间的通信 pinia

① 安装:

npm install pinia

 ② 创建文件夹

③ index.ts

import { createPinia } from 'pinia'
// createPinia方法可以用于创建大仓库
let store = createPinia()
export default store

  ④ main.ts 

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'import store from './store'const app = createApp(App)app.use(store)
app.use(router)
app.mount('#app')

⑤ 在modules文件下创建一个小仓库info.ts

import { defineStore } from "pinia";// defineStore方法接收两个参数
// 第一个参数接收:仓库的名字
// 第二个参数:仓库的配置对象
// 返回一个函数作用就是让组件可以获取到仓库的数据
let useInfoStore = defineStore('info', {// 存储数据:statestate: () => {return {num:10,arr:[1,2,3]}},actions: {updateNum(val){// this就是仓库的数据对象this.num+=val}},getters: {// 计算一下arr数组的和total() {let ress = this.arr.reduce((pre,nex)=> {return pre+nex},0)return ress}}
})// 对外暴露出去
export default useInfoStore

⑥ 在页面使用

<template><div>pinia--{{ infoStore.num }}---总和:{{ infoStore.total }}<button @click="addNum">修改仓库数据</button></div>
</template><script setup lang="ts">
import useInfoStore from '../../store/modules/info'
// 获取小仓库对象
let infoStore = useInfoStore()
console.log('infoStore',infoStore);const addNum = () => {// 仓库调用自身的方法修改仓库的数据(也可以传参数)infoStore.updateNum(6);
}
</script>

    以上为pinia选择式API的写法
---------------------------------------------------------------------------------------------------------
   以下为pinia组合式API 的写法

① 新建一个仓库zuhe.ts 

import { defineStore } from "pinia";
import {ref,computed} from 'vue'
let useZuheStore = defineStore('zuhe', () => {// 箭头函数返回一个对象:属性与方法可以提供给组件使用let data = ref([{id:1, name:'小黑子'},{id:2, name:'背带裤'},])let arr =ref([1,2,3])const total = computed(() => {return arr.value.reduce((pre,nex)=> {return pre+nex},0)})const upData = () => {data.value.push({ id:3, name:'梳中分'})}return {data,arr,upData,total}
})// 对外暴露出去
export default useZuheStore

 ② 页面使用

<template><div>页面使用:{{ zuheStore.data }} ---总和:{{zuheStore.total}}</div><button @click="updateData">修改仓库数据</button>
</template><script setup lang="ts">import useZuheStore from '../../store/modules/zuhe'let zuheStore = useZuheStore()const updateData = () => {zuheStore.upData()}
</script>

八、插槽 

分为三种插槽:默认插槽,具名插槽,作用域插槽

① 默认插槽

父组件slotDemo.vue

<template><div>父级</div><slotDemoSon><h3>小黑子</h3></slotDemoSon>
</template><script setup lang="ts">
import slotDemoSon from './slotDemoSon.vue';</script>

子组件slotDemoSon.vue

<template><div>Son--默认插槽</div><slot></slot>
</template><script setup lang="ts"></script>

② 具名插槽

父组件slotDemo.vue

<template><div>父级</div><slotDemoSon><!-- 具名插槽 --><template v-slot:xiao><div>我是填充具名插槽xiao位置结构</div></template><template #hei>  <!--v-slot 可以简写为#号-->><div>我是填充具名插槽hei位置结构</div></template></slotDemoSon>
</template><script setup lang="ts">
import slotDemoSon from './slotDemoSon.vue';</script>

子组件slotDemoSon.vue

<template><div>Son--具名插槽</div><slot name="xiao"></slot><slot name="hei"></slot>
</template>

③ 作用域插槽

可以传递数据的插槽。子组件可以将数据回传给父组件,父组件可以决定这些回传数据是以何种结构或者外观(样式)在子组件内部去展示

父组件slotDemo.vue

<template><div>父级</div><slotDemoSon :arrList="arrList"><template v-slot="{data,index}"> <!--回传过来是对象所以可以解构--><p>{{ data.name }}--{{index}}</p></template></slotDemoSon>
</template>
<script setup lang="ts">
import slotDemoSon from './slotDemoSon.vue';
import { ref } from 'vue'let arrList = ref([{ id:1, name:'小黑', type:false},{ id:2, name:'小白', type:true},{ id:3, name:'小蓝', type:false},
])
</script>

子组件slotDemoSon.vue

<template><div>作用域插槽</div><ul><li v-for="(item,index) in arrList" :key="item.id"><!-- 作用域插槽:可以将数据回传给父组件 --><slot :data="item" :index="index"></slot></li></ul>
</template><script setup lang="ts">
defineProps(['arrList'])
</script>

父组件可以决定这些回传数据是以何种结构或者外观在子组件内部去展示

上面父组件用了p标签进行展示

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

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

相关文章

Qt实现TFTP Server和 TFTP Client(一)

1 概述 TFTP协议是基于UDP的简单文件传输协议&#xff0c;协议双方为Client和Server.Client和Server之间通过5种消息来传输文件,消息前两个字节Code是消息类型&#xff0c;消息内容随消息类型不同而不同。传输模式有三种&#xff1a;octet,netascii和mail&#xff0c;octet为二…

Flask 与小程序 的图片数据交互 过程及探讨研究学习

今天不知道怎么的&#xff0c;之前拿编程浪子地作品抄过来粘上用好好的&#xff0c;昨天开始照片突的就不显示了。 今天不妨再耐味地细细探究一下微信小程序wxml 和flask服务器端是怎么jpg图片数据交互的。 mina/pages/food/index.wxml <!--index.wxml--> <!--1px …

上位机图像处理和嵌入式模块部署(qmacvisual图像识别)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 所谓图像识别&#xff0c;就是对图像进行分类处理&#xff0c;比如说判断图像上面的物体是飞机、还是蝴蝶。在深度学习和卷积神经网络CNN不像现在这…

欧科云链:2024将聚焦发展与安全,用技术助力链上数据安全和合规

近期&#xff0c;OpenAI和Web3.0两大新技术发展势头迅猛。OpenAI 再次引领AI领域的新浪潮&#xff0c;推出了创新的文本转视频模型——Sora&#xff0c;Sora 可以创建长达60 秒的视频&#xff0c;包含高度详细的场景、複杂的摄像机运动以及情感丰富角色&#xff0c;再次将AI 的…

lora-scripts 训练IP形象

CodeWithGPU | 能复现才是好算法CodeWithGPU | GitHub AI算法复现社区&#xff0c;能复现才是好算法https://www.codewithgpu.com/i/Akegarasu/lora-scripts/lora-trainstable-diffusion打造自己的lora模型&#xff08;使用lora-scripts&#xff09;-CSDN博客文章浏览阅读1.1k次…

怿星科技Neptune CHT-S测试系统,让智能座舱测试更加高效便捷

随着汽车“智能化”浪潮的推进&#xff0c;汽车的智能化水平正在持续刷新行业认知。在这股智能化潮流中&#xff0c;智能座舱作为客户体验最为直观的部分&#xff0c;其重要性不言而喻。倘若座舱设备出现死机、黑屏、卡顿等现象&#xff0c;都将对客户的使用体验产生非常大的影…

ChatGPT无法登录,提示我们检测到可疑的登录行为?如何解决?

OnlyFans 订阅教程移步&#xff1a;【保姆级】2024年最新Onlyfans订阅教程 Midjourney 订阅教程移步&#xff1a; 【一看就会】五分钟完成MidJourney订阅 GPT-4.0 升级教程移步&#xff1a;五分钟开通GPT4.0 如果你需要使用Wildcard开通GPT4、Midjourney或是Onlyfans的话&am…

c语言--内存函数的使用(memcpy、memcmp、memset、memmove)

目录 一、memcpy()1.1声明1.2参数1.3返回值1.4memcpy的使用1.5memcpy模拟使用1.6注意 二、memmove()2.1声明2.2参数2.3返回值2.4使用2.5memmove&#xff08;&#xff09;模拟实现 三、memset3.1声明3.2参数3.3返回值3.4使用 四、memcmp()4.1声明4.2参数4.3返回值4.4使用 五、注…

【python】Anaconda安装后打不开jupyter notebook(网页不自动跳出)

文章目录 一、遇到的问题&#xff1a;jupyter notebook网页不自动跳出&#xff08;一&#xff09;输入jupyter notebook命令&#xff08;二&#xff09;手动打开网页 二、解决办法&#xff1a;指定浏览器&#xff08;一&#xff09;找文件 jupyter_notebook_config.py&#xff…

自媒体用ChatGPT批量洗稿软件V5.9环境配置/软件设置教程【汇总】

大家好&#xff0c;我是淘小白~ 首先&#xff0c;感谢大家的支持~~ ChatGPT采集洗稿软件V5.9版本更新&#xff0c;此次版本更新修改增加了一些内容&#xff1a; 1、自定义多条指令&#xff0c;软件自动判断指令条数&#xff0c;进行输入 2、增加谷歌浏览多账号轮询&#xf…

读算法的陷阱:超级平台、算法垄断与场景欺骗笔记18_竞争市场

1. 竞争市场 1.1. 算法、大数据、超级平台的风起云涌似乎预示了市场竞争机制的加速终结&#xff0c;而我们似乎也对这种市场机制的衰退见怪不怪 1.1.1. 它有效节省了消费者的搜寻成本&#xff0c;降低了市场准入壁垒&#xff0c;开辟了市场扩张与准入之间的崭新通道&#xff…

Spark-Scala语言实战(5)

在之前的文章中&#xff0c;我们学习了如何在scala中定义与使用集合和元组。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 Spark-Scala语言实战&#xff08;…

c++核心学习5

4.6继承 有些类与类之间存在特殊的关系&#xff0c;例如下图中&#xff1a; 我们发现&#xff0c;定义这些类时&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。这个时候我们就可以考虑利用继承的技术&#xff0c;减少重复代码 4.6.1继承的基本语法…

VTK9.2.0+Qt5.14.0 绘制点云

背景 为了显示结构光重建后的点云&#xff0c;开发QT5.14.0VTK9.2.0的上位机软件&#xff0c;用于对结构光3D相机进行控制&#xff0c;并接收传输回来的3D数据&#xff0c;显示在窗口中。 配置QT和VTK VTK9.2.0下载源码&#xff0c;用Cmake编译&#xff0c;编译好的VTK9.2.0…

去中心化的 AI 数据供应:认识Grass,参与Grass

去中心化的 AI 数据供应&#xff1a;认识Grass&#xff0c;参与Grass &#x1f44b;&#xff1a;邀请链接☘️&#xff1a;Intro❓&#xff1a;看好Grass和即将推出的L2的原因有哪些&#xff1f;&#x1f4a1;&#xff1a;展望&#x1f50d;&#xff1a;总结 &#x1f44b;&…

说说webpack的构建流程?

文章目录 一、运行流程初始化流程编译构建流程compile 编译make 编译模块build module 完成模块编译 输出流程seal 输出资源emit 输出完成 二、小结参考文献 一、运行流程 webpack 的运行流程是一个串行的过程&#xff0c;它的工作流程就是将各个插件串联起来 在运行过程中会…

python学生作业管理系统flask-django-nodejs-php

课题主要分为三大模块&#xff1a;即管理员模块和学生、教师模块&#xff0c;主要功能包括&#xff1a;学生、教师、作业信息、学习模块、教学评价、学习情况等&#xff1b; 关键词&#xff1a;学生作业管理系统&#xff1b;作业信息 目录 摘 要 I Abstrac II 目录 III 1绪论 1…

matlab实现机器学习svm

一、目的和要求 1.编程实现SVM训练函数和预测函数&#xff1b; 2.绘制线性和非线性边界&#xff1b; 3.编写线性核函数 二、算法 1.线性svm&#xff1a; 分离超平面&#xff1a;wxb0&#xff0c;对于线性可分的数据集来说&#xff0c;这样的超平面有无穷多个&#xff08;…

ARM32day4

VID_20240319_210515 1.思维导图 2.实现三个LED灯亮灭 .text .global _start _start: 使能GPIO外设时钟 LDR R0,0x50000A28 LDR R1,[R0]使能GPIOE ORR R1,R1,#(0X1<<4)使能GPIOF ORR R1,R1,#(0X1<<5) STR R1,[R0]设置引脚状态 LDR R0,0X50006000 LDR R1,[R0…

SQL:窗口函数之OVER()

窗口函数 通用格式 “函数 OVER (PARTITION BY 分组 ORDER BY 排序依据 升降序)”。 这里记录下OVER() 以及搭配LEAD/LAG函数的使用方法&#xff08;执行平台Impala&#xff09; 目录 OVER函数1、不加条件的OVER函数——得到所有的汇总结果2、仅有排序的OVER函数——得到按顺序…